[Перевод] Как устроен namedtuple или динамическое создание типов

Мы в Буруках любим не только людей и цифры. Мы также без устали совершенствуемся во владении нашим основным инструментом, языком Python. Ссылка для тех, кто хочет совершенствоваться с нами. В этой статье-переводе автор разбирает устройство
namedtuple и по ходу рассказывает об одной из основных концепций языка.

Пару дней назад я был на пути в Сан-Франциско. Интернета в самолёте не было, поэтому я читал исходники стандартной библиотеки Python 2.7. Реализация namedtuple
показалась мне особенно интересной, наверное, потому, что на деле всё гораздо проще, чем я думал раньше.

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

Код

<code class="python">################################################################################ ### namedtuple ################################################################################</code>Ого! Впечатляющий заголовок, правда?

В начале, как и полагается, определение функции, и пример хорошего доктеста.

<code class="python">def namedtuple(typename, field_names, verbose=False, rename=False): """Возвращает новый подкласс кортежа с именованными полями. >>> Point = namedtuple('Point', 'x y') >>> Point.__doc__ # докстринг нового класса 'Point(x, y)' >>> p = Point(11, y=22) # создание экземпляра с позиционными и именованными аргументами >>> p[0] + p[1] # индексируется как обычный кортеж 33 >>> x, y = p # распаковывается как обычный кортеж >>> x, y (11, 22) >>> p.x + p.y # поля доступны по имени 33 >>> d = p._asdict() # конвертируется в словарь >>> d['x'] 11 >>> Point(**d) # создаётся из словаря Point(x=11, y=22) >>> p._replace(x=100) # обновляет значение именованного поля Point(x=100, y=22) """ </code>Потом начинаются разборки с аргументами. Обратите внимание на использование basestring
в вызове
isinstance — так мы определим, что работаем со строкой, если тип объекта unicode
или
str (это точно работает в Python < 3.0).

<code class="python"> # Парсим и валидируем имена полей. Валидация служит двум целям: # генерация информативных сообщений об ошибках # и предотвращение атак внедрением в шаблоны. if isinstance(field_names, basestring): field_names = field_names.replace(',', ' ').split() # имена разделены пробелами и/или запятыми </code>Если установлен атрибут rename
, то все неправильные названия полей будут переименованы соответственно их позициям.

<code class="python">    field_names = tuple(map(str, field_names))
    if rename:
        names = list(field_names)
        seen = set()
        for i, name in enumerate(names):
            if (not all(c.isalnum() or c=='_' for c in name) or _iskeyword(name)
                or not name or name[0].isdigit() or name.startswith('_')
                or name in seen):
                names[i] = '_%d' % i
            seen.add(name)
        field_names = tuple(names)
</code>
Обратите внимание на генераторное выражение, обёрнутое в
all(). Такая запись, all(bool_expr(x) for x in things)
, — крайне удобный способ описать желаемый результат в одном выражении.

<code class="python">    for name in (typename,) + field_names:
        if not all(c.isalnum() or c=='_' for c in name):
            raise ValueError(
                'Type names and field names can only contain alphanumeric characters and underscores: %r' % name
            )
        if _iskeyword(name):
            raise ValueError('Type names and field names cannot be a keyword: %r' % name)
        if name[0].isdigit():
            raise ValueError('Type names and field names cannot start with a number: %r' % name)
</code>
Проверочка на повторения имён:

<code class="python">    seen_names = set()
    for name in field_names:
        if name.startswith('_') and not rename:
            raise ValueError('Field names cannot start with an underscore: %r' % name)
        if name in seen_names:
            raise ValueError('Encountered duplicate field name: %r' % name)
        seen_names.add(name)
</code>
А теперь начинается настоящее веселье. (Я уверен, что создание типа данных во время исполнения — это весело). Подготавливаем разным образом имена полей для внедрения в шаблон кода. Интересно использование текстового представления кортежа и нотации срезов для определения
argtxt.

<code class="python"> # Создадим и заполним шаблон класса numfields = len(field_names) argtxt = repr(field_names).replace("'", "")[1:-1] # представление кортежа без кавычек и скобок reprtxt = ', '.join('%s=%%r' % name for name in field_names) </code>И вот что на самом деле творится под капотом namedtuple
. Эта строка впоследствие превратится в Python-код.

<code class="python">    template = '''class %(typename)s(tuple):
        '%(typename)s(%(argtxt)s)' \n
        __slots__ = () \n
        _fields = %(field_names)r \n

        def __new__(_cls, %(argtxt)s):
            'Create new instance of %(typename)s(%(argtxt)s)'
            return _tuple.__new__(_cls, (%(argtxt)s)) \n

        @classmethod
        def _make(cls, iterable, new=tuple.__new__, len=len):
            'Make a new %(typename)s object from a sequence or iterable'
            result = new(cls, iterable)
            if len(result) != %(numfields)d:
                raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result))
            return result \n

        def __repr__(self):
            'Return a nicely formatted representation string'
            return '%(typename)s(%(reprtxt)s)' %% self \n

        def _asdict(self):
            'Return a new OrderedDict which maps field names to their values'
            return OrderedDict(zip(self._fields, self)) \n

        __dict__ = property(_asdict) \n

        def _replace(_self, **kwds):
            'Return a new %(typename)s object replacing specified fields with new values'
            result = _self._make(map(kwds.pop, %(field_names)r, _self))
            if kwds:
                raise ValueError('Got unexpected field names: %%r' %% kwds.keys())
            return result \n

        def __getnewargs__(self):
            'Return self as a plain tuple.  Used by copy and pickle.'
            return tuple(self) \n\n
        
        ''' % locals()
</code>
Собственно, это и есть шаблон нашего нового класса.

Использование
locals() для строковой интерполяции мне кажется очень удобным. Питону не хватает простой интерполяции локальных переменных. В Groovy и CoffeeScript, например, можно написать что-то вроде "{name} is {some_value}"
. Но я думаю, что этот Python-вариант вполне сойдёт:
"{name} is {some_value}".fCL_Prefix_ormat(**locals())
.

Вы, наверное, заметили, что
__slots__ определяется как пустой кортеж. Питон в таком случае не использует для экземпляров словари в качестве пространств имён, что немного экономит ресурсы. Благодаря неизменяемости, которая наследуется от родительского класса (tuple
), и невозможности добавлять новые атрибуты (потому что
__slots__ = ()), экземпляры namedtuple
-типов являются объектами-значениями.

Идём дальше. На каждое имя создаётся свойство только для чтения.
_itemgetter — это itemgetter
из модуля
operator, который возвращает функцию одного аргумента, что как раз подходит для свойства.

<code class="python"> for i, name in enumerate(field_names): template += " %s = _property(_itemgetter(%d), doc='Alias for field number %d')\n" % (name, i, i) if verbose: print template </code>Итак, у нас есть грандиозная строчка с питонячьим кодом. Что с ней делать? Выполнение в ограниченном пространстве имён кажется разумным. Посмотрите, как тут используется exec ... in
:

<code class="python">    # Исполним полученный код во временном пространстве имён.
    # Не забываем о поддержке трассировщиков, определяем значение
    # frame.f_globals['__name__']
    namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
                     OrderedDict=OrderedDict, _property=property, _tuple=tuple)
    try:
        exec template in namespace
    except SyntaxError, e:
        raise SyntaxError(e.message + ':\n' + template)
    result = namespace[typename]
</code>
Очень хитро! Идея исполнить строку кода в изолированном пространстве имён, а затем вытащить из него новый тип непривычна для меня. За подробностями об
exec идём в пост Армина Ронахера.

Дальше немного магии, чтобы определить __module__
нового класса как модуль, который вызвал
namedtuple:

<code class="python"> try: result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__') except (AttributeError, ValueError): pass </code>и на этом всё!

<code class="python"> return result </code>Просто, не так ли?

Мысли о реализации

Самой интересной для меня деталью описанного выше кода стало динамическое исполнение строки кода в пространстве имён, которое создаётся исключительно для одного этого исполнения. Этот ход подчёркивает простоту модели данных Питона: все пространства имён, включая модули и классы, являются по сути словарями. Изучение внутренностей namedtuple
снова доказывает мощь такой простоты.
Используя эту технику мы могли бы упростить валидацию названий полей, и вместо

<code class="python">for name in (typename,) + field_names:
    if not all(c.isalnum() or c=='_' for c in name):
        raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
    if _iskeyword(name):
        raise ValueError('Type names and field names cannot be a keyword: %r' % name)
    if name[0].isdigit():
        raise ValueError('Type names and field names cannot start with a number: %r' % name)
</code>
можно было бы написать

<code class="python">for name in (typename,) + field_names:
    try:
        exec ("%s = True" % name) in {}
    except (SyntaxError, NameError):
        raise ValueError('Invalid field name: %r' % name)
</code>
чтобы прямо и коротко протестировать валидность идентификатора. Но в этом случае мы потеряем точность в описании проблемы при возникновении ошибки. А так как это стандартная библиотека, то явные сообщения об ошибках делают текущую реализацию лучшим выбором.

Между нами только
find

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

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

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Третья проверка кода проекта Chromium с помощью анализатора PVS-Studio

Браузер Chromium очень быстро развивается. Например, когда в 2011 году мы впервые проверили этот проект (solution), он состоял из 473 проектов. Сейчас, он состоит уже из 1169 проектов. Нам было интересно, смогли ли разработчики Google сохранить высочайшее качество кода, при такой скорости развития Chromium. Да, смогли.

Chromium
Chromium — веб-браузер с открытым исходным кодом, разработанный компанией Google. На основе Chromium создаётся браузер Google Chrome. На странице "Get the Code" можно узнать, как скачать исходный код этого проекта.

Немного общей информации
Раньше мы уже проверяли проект Chromium, о чём имеется две статьи: первая проверка (23.05.2011), вторая проверка (13.10.2011). И всё время находили ошибки. Это тонкий намёк о пользе анализаторов кода.

Сейчас (исходный код проекта скачан в июле 2013) Chromium состоит из 1169 проектов. Общий объем исходного кода на языке Си/Си++ составляет 260 мегабайт. Дополнительно к этому можно прибавить ещё 450 мегабайт используемых внешних библиотек.

Если взять нашу первую проверку проекта Chromium в 2011 году, то можно заметить — объем внешних библиотек в целом не изменился. Зато код, самого проекта существенно вырос c 155 мегабайт до 260 мегабайт.

Ради интереса посчитаем цикломатическую сложность
В анализаторе PVS-Studio есть возможность поиска функций с большой цикломатической сложностью. Как правило, такие функции являются кандидатами для рефакторинга. Проверив 1160 проектов, мне естественно стало интересно, какой из них можно назвать рекордсменом в номинации «самая сложная функция».

Самая максимальная цикломатическая сложность, равная 2782, принадлежит функции ValidateChunkAMD64() в проекте Chromium. Но её пришлось дисквалифицировать из состязания. Функция находится в файле validator_x86_64.c, который является автогенерируемым. Жаль. А то был бы эпичный рекордсмен. Я и близко с такой цикломатической сложностью не сталкивался.

Таким образом, первые три места получают следующие функции:
  1. Библиотека WebKit. Функция HTMLTokenizer::nextToken() в файле htmltokenizer.cpp. Цикломатическая сложность 1106.
  2. Библиотека Mesa. Функция _mesa_glsl_lex() в файле glsl_lexer.cc. Цикломатическая сложность 1088.
  3. Библиотека usrsctplib (какой-то безызвестный спортсмен). Функция sctp_setopt() в файле htmltokenizer.cpp. Цикломатическая сложность 1026.
Если кто-то не знает, что такое цикломатическая сложность 1000, то пусть и не знает. Психическое здоровье будет лучше :). В общем, много это.

Качество кода
Что я могу сказать о качестве кода проекта Chromium? Качество по-прежнему великолепное. Да, как и в любом большом проекте, всегда можно найти ошибки. Но если поделить их количество на объем кода, их плотность будет ничтожна. Это очень хороший код с очень малым количеством ошибок. Вручаю медальку за чистый код. Предыдущая медалька досталась проекту Casablanca (C++ REST SDK) от компании Microsoft.
Рисунок 1. Медалька создателям Chromium.
Рисунок 1. Медалька создателям Chromium.

За компанию вместе с Chromium были проверенные входящие в него сторонние библиотеки. Но описывать найденные в них ошибки не интересно. Тем более я просматривал отчёт очень поверхностно. Нет, я вовсе не плохой человек. Я бы посмотрел на вас, если бы вы попробовали полноценно изучить отчёт о проверке 1169 проектов. То, что я заметил при беглом просмотре, я поместил в базу примеров ошибок. В этой статье я хочу коснуться только тех ошибок, которые успел заметить в коде самого Chromium (его плагинов и тому подобного).

Раз проект Chromium, такой хороший, так зачем я буду приводить примеры найденных ошибок? Всё очень просто. Я хочу продемонстрировать мощь анализатора PVS-Studio. Если он сумел найти ошибки в Chromium, то инструмент заслуживает вашего внимания.

Анализатор сумел прожевать десятки тысяч файлов, общим объемом 710 мегабайт, и не загнулся от этого. Не смотря на то, что проект разрабатывается высококвалифицированными разработчиками и проверяется различными инструментами, PVS-Studio всё равно умудрился выявить дефекты. Это замечательное достижение! И последнее — он сделал это за разумное время (около 5 часов) за счёт параллельной проверки (AMD FX-8320/3.50 GHz/eight-core processor, 16.0 GB RAM).

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

Замеченное N1 — опечатки
<code class="cpp">Vector3dF
Matrix3F::SolveEigenproblem(Matrix3F* eigenvectors) const
{
  // The matrix must be symmetric.
  const float epsilon = std::numeric_limits<float>::epsilon();
  if (std::abs(data_[M01] - data_[M10]) > epsilon ||
      std::abs(data_[M02] - data_[M02]) > epsilon ||
      std::abs(data_[M12] - data_[M21]) > epsilon) {
    NOTREACHED();
    return Vector3dF();
  }
  ....
}</code>
V501 There are identical sub-expressions to the left and to the right of the '-' operator: data_[M02] — data_[M02] matrix3_f.cc 128

Надо проверить, что матрица размером 3x3 симметрична.
Рисунок 2. Матрица 3x3.
Рисунок 2. Матрица 3x3.

Для этого надо сравнить следующие элементы:
  • M01 и M10
  • M02 и M20
  • M12 и M21
Скорее всего, код писался с помощью технологии Copy-Paste. В результате ячейка M02 сравнивается сама с собой. Вот такой вот забавный класс матрицы.

Другая простая опечатка:
<code class="cpp">bool IsTextField(const FormFieldData& field) {
  return
    field.form_control_type == "text" ||
    field.form_control_type == "search" ||
    field.form_control_type == "tel" ||
    field.form_control_type == "url" ||
    field.form_control_type == "email" ||
    field.form_control_type == "text";
}</code>
V501 There are identical sub-expressions 'field.form_control_type == «text»' to the left and to the right of the '||' operator. autocomplete_history_manager.cc 35

Два раза происходит сравнение со строкой «text». Это подозрительно. Возможно, одна строка просто лишняя. А может быть, отсутствует другое нужное здесь сравнение.

Замеченное N2 — противоположные условия
<code class="cpp">static void ParseRequestCookieLine(
    const std::string& header_value,
    ParsedRequestCookies* parsed_cookies)
{
  std::string::const_iterator i = header_value.begin();
  ....
  if (*i == '"') {
    while (i != header_value.end() && *i != '"') ++i;
  ....
}</code>
V637 Two opposite conditions were encountered. The second condition is always false. Check lines: 500, 501. web_request_api_helpers.cc 500

Мне кажется, этот код должен был пропускать текст, обрамленный двойными кавычками. Но на самом деле, этот код ничего не делает. Условие сразу ложно. Для наглядности, напишу псевдокод, чтобы подчеркнуть суть ошибки:
<code class="cpp">if ( A == 'X' ) {
  while ( .... && A != 'X' ) ....;</code>
Скорее всего, здесь забыли сдвинуть указатель на один символ и код должен выглядеть так:
<code class="cpp">if (*i == '"') {
  ++i;
  while (i != header_value.end() && *i != '"') ++i;</code>

Замеченное N3 — неудачное удаление элементов
<code class="cpp">void ShortcutsProvider::DeleteMatchesWithURLs(
  const std::set<GURL>& urls)
{
  std::remove_if(matches_.begin(),
                 matches_.end(),
                 RemoveMatchPredicate(urls));
  listener_->OnProviderUpdate(true);
}</code>
V530 The return value of function 'remove_if' is required to be utilized. shortcuts_provider.cc 136

Для удаления элементов из контейнера используется функция std::remove_if(). Но используется неправильно. На самом деле, remove_if() ничего не удаляет. Она сдвигает элементы в начало и возвращает итератор на мусор. Удалять мусор нужно самостоятельно, вызывая у контейнеров функцию erase(). См. также статью в Wikipedia "Erase-remove idiom".

Правильный код:
<code class="cpp">matches_.erase(std::remove_if(.....), matches_.end());</code>

Замеченное N4 — вечная путаница с SOCKET
SOCKET в мире Linux, это целочисленный ЗНАКОВЫЙ тип данных.

SOCKET в мире Windows, это целочисленный БЕЗЗНАКОВЫЙ тип данных.

В заголовочных файлах Visual C++ тип SOCKET объявлен так:
<code class="cpp">typedef UINT_PTR SOCKET;</code>
Однако про это постоянно забывают и пишут код следующего вида:
<code class="cpp">class NET_EXPORT_PRIVATE TCPServerSocketWin {
   ....
   SOCKET socket_;
   ....
};

int TCPServerSocketWin::Listen(....) {
  ....
  socket_ = socket(address.GetSockAddrFamily(),
                   SOCK_STREAM, IPPROTO_TCP);
  if (socket_ < 0) {
    PLOG(ERROR) << "socket() returned an error";
    return MapSystemError(WSAGetLastError());
  }
  ....
}</code>
V547 Expression 'socket_ < 0' is always false. Unsigned type value is never < 0. tcp_server_socket_win.cc 48

Переменная беззнакового типа всегда больше или равна нулю. Это значит, что проверка 'socket_ < 0' не имеет смысла. Если при работе программы сокет не удастся открыть, эта ситуация не будет корректно обработана.

Замеченное N5 — путаница с операциями ~ и !
<code class="cpp">enum FontStyle {
  NORMAL = 0,
  BOLD = 1,
  ITALIC = 2,
  UNDERLINE = 4,
};

void LabelButton::SetIsDefault(bool is_default) {
  ....
  style = is_default ? style | gfx::Font::BOLD :
                       style & !gfx::Font::BOLD;
  ....
}</code>
V564 The '&' operator is applied to bool type value. You've probably forgotten to include parentheses or intended to use the '&&' operator. label_button.cc 131

Как мне кажется, код должен был работать так:
  • Если переменная 'is_default' равна true, то всегда нужно выставить бит, отвечающий за стиль BOLD.
  • Если переменная 'is_default' равна false, то всегда нужно сбросить бит, отвечающий за стиль BOLD.
Однако, выражение «style & !gfx::Font::BOLD» работает не так, как ожидает программист. Результат операции "!gfx::Font::BOLD" будет равен 'false'. Или другими словами, 0. Код написанный выше эквивалентен этому:
<code class="cpp">style = is_default ? style | gfx::Font::BOLD : 0;</code>
Чтобы код работал правильно, следовало использовать операцию '~':
<code class="cpp">style = is_default ? style | gfx::Font::BOLD :
                     style & ~gfx::Font::BOLD;</code>

Замеченное N6 — подозрительное создание временных объектов
<code class="cpp">base::win::ScopedComPtr<IDirect3DSurface9> scaler_scratch_surfaces_[2];

bool AcceleratedSurfaceTransformer::ResizeBilinear(
  IDirect3DSurface9* src_surface, ....)
{
  ....
  IDirect3DSurface9* read_buffer = (i == 0) ?
    src_surface : scaler_scratch_surfaces_[read_buffer_index];
  ....
}</code>
V623 Consider inspecting the '?:' operator. A temporary object of the 'ScopedComPtr' type is being created and subsequently destroyed. Check second operand. accelerated_surface_transformer_win.cc 391

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

На первый взгляд здесь всё просто. В зависимости от условия, мы выбираем указатель 'src_surface' или один из элементов массива 'scaler_scratch_surfaces_'. Массив состоит из объектов типа base::win::ScopedComPtr<IDirect3DSurface9>, которые могут автоматически приводиться к указателю на IDirect3DSurface9.

Дьявол кроется в деталях.

Тернарный оператор '?:' не может возвращать разный тип в зависимости от условия. Поясню на простом примере.
<code class="cpp">int A = 1;
auto X = v ? A : 2.0;</code>
Оператор ?: возвращает тип 'double'. В результате переменная 'X' будет тоже иметь тип double. Но это не важно. Важно, что переменная 'A' будет неявно расширена до типа 'double'!

Беда возникает, если написать что-то подобное:
<code class="cpp">CString s1(L"1");
wchar_t s2[] = L"2";
bool a = false;
const wchar_t *s = a ? s1 : s2;</code>
В результате выполнения этого кода переменная 's' будет указывать на данные, находящиеся внутри временного объекта типа CString. Проблема в том, что этот объект будет сразу уничтожен.

Вернемся теперь к исходному коду Chromium.
<code class="cpp">IDirect3DSurface9* read_buffer = (i == 0) ?
    src_surface : scaler_scratch_surfaces_[read_buffer_index];</code>
Здесь произойдет следующее, если выполнится условие 'i == 0':
  • из указателя 'src_surface' будет сконструирован временный объект типа base::win::ScopedComPtr<IDirect3DSurface9>;
  • временный объект будет неявно приведён к указателю типа IDirect3DSurface9 и помещён в переменную read_buffer;
  • временный объект будет разрушен.
Я не знаю логику работы программы и класса ScopedComPtr и затрудняюсь сказать, могут ли возникнуть негативные последствия или нет. Скорее всего, в конструкторе счётчик количества ссылок будет увеличен, а в деструкторе уменьшен. И всё будет хорошо.

Если это не так, то ненароком можно получить не валидный указатель или сломать подсчёт ссылок.

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

Вот ещё одно такое подозрительное место:
<code class="cpp">typedef
  GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle;

DWORD HandlePolicy::DuplicateHandleProxyAction(....)
{
  ....
  base::win::ScopedHandle remote_target_process;
  ....
  HANDLE target_process =
    remote_target_process.IsValid() ?
      remote_target_process : ::GetCurrentProcess();
  ....
}</code>
V623 Consider inspecting the '?:' operator. A temporary object of the 'GenericScopedHandle' type is being created and subsequently destroyed. Check third operand. handle_policy.cc 81

Замеченное N7 — повторяющиеся проверки
<code class="cpp">string16 GetAccessString(HandleType handle_type,
                         ACCESS_MASK access) {
  ....
  if (access & FILE_WRITE_ATTRIBUTES)
    output.append(ASCIIToUTF16("\tFILE_WRITE_ATTRIBUTES\n"));
  if (access & FILE_WRITE_DATA)
    output.append(ASCIIToUTF16("\tFILE_WRITE_DATA\n"));
  if (access & FILE_WRITE_EA)
    output.append(ASCIIToUTF16("\tFILE_WRITE_EA\n"));
  if (access & FILE_WRITE_EA)
    output.append(ASCIIToUTF16("\tFILE_WRITE_EA\n"));
  ....
}</code>
V581 The conditional expressions of the 'if' operators situated alongside each other are identical. Check lines: 176, 178. handle_enumerator_win.cc 178

Если установлен флаг FILE_WRITE_EA, то стока "\tFILE_WRITE_EA\n" будет добавлена дважды. Очень подозрительный код.

Аналогичную странную картину можно наблюдать здесь:
<code class="cpp">static bool PasswordFormComparator(const PasswordForm& pf1,
                                   const PasswordForm& pf2) {
  if (pf1.submit_element < pf2.submit_element)
    return true;
  if (pf1.username_element < pf2.username_element)
    return true;
  if (pf1.username_value < pf2.username_value)
    return true;
  if (pf1.username_value < pf2.username_value)
    return true;
  if (pf1.password_element < pf2.password_element)
    return true;
  if (pf1.password_value < pf2.password_value)
    return true;

  return false;
}</code>
V581 The conditional expressions of the 'if' operators situated alongside each other are identical. Check lines: 259, 261. profile_sync_service_password_unittest.cc 261

Два раза повторяется проверка «pf1.username_value < pf2.username_value». Возможна, одна строка просто лишняя. А возможно, забыли проверить что-то другое, и должно быть написано совсем другое условие.

Замеченное N8 — «одноразовые» циклы
<code class="cpp">ResourceProvider::ResourceId
PictureLayerImpl::ContentsResourceId() const
{
  ....
  for (PictureLayerTilingSet::CoverageIterator iter(....);
       iter;
       ++iter)
  {
    if (!*iter)
      return 0;

    const ManagedTileState::TileVersion& tile_version = ....;

    if (....)
      return 0;

    if (iter.geometry_rect() != content_rect)
      return 0;

    return tile_version.get_resource_id();
  }
  return 0;
}</code>
V612 An unconditional 'return' within a loop. picture_layer_impl.cc 638

С этим циклом что-то не так. Цикл выполняет только одну итерацию. В конце цикла находится безусловный оператор return. Возможные причины:
  • Так и задумано. Но это очень сомнительно. Зачем тогда создавать цикл, создавать итератор и т.д.
  • Вместо одного из 'return', должно быть написано 'continue'. Но тоже сомнительно.
  • Скорее всего, перед последним 'return' пропущено какое-то условие.
Попались и другие странные циклы, которые выполняются только раз:
<code class="cpp">scoped_ptr<ActionInfo> ActionInfo::Load(....)
{
  ....
  for (base::ListValue::const_iterator iter = icons->begin();
        iter != icons->end(); ++iter)
  {
    std::string path;
    if (....);
      return scoped_ptr<ActionInfo>();
    }

    result->default_icon.Add(....);
    break;
  }
  ....
}</code>
V612 An unconditional 'break' within a loop. action_info.cc 76
<code class="cpp">const BluetoothServiceRecord* BluetoothDeviceWin::GetServiceRecord(
    const std::string& uuid) const
{
  for (ServiceRecordList::const_iterator iter =
         service_record_list_.begin();
       iter != service_record_list_.end();
       ++iter)
  {
    return *iter;
  }
  return NULL;
}</code>
V612 An unconditional 'return' within a loop. bluetooth_device_win.cc 224

Замеченное N9 — неинициализированные переменные
<code class="cpp">HRESULT IEEventSink::Attach(IWebBrowser2* browser) {
  DCHECK(browser);
  HRESULT result;
  if (browser) {
    web_browser2_ = browser;
    FindIEProcessId();
    result = DispEventAdvise(web_browser2_, &DIID_DWebBrowserEvents2);
  }
  return result;
}</code>
V614 Potentially uninitialized variable 'result' used. ie_event_sink.cc 240

Если указатель 'browser' равен нулю, то функция вернет неинициализированную переменную.

Другой фрагмент кода:
<code class="cpp">void SavePackage::GetSaveInfo() {
  ....
  bool skip_dir_check;
  ....
  if (....) {
    ....->GetSaveDir(...., &skip_dir_check);
  }
  ....
  BrowserThread::PostTask(BrowserThread::FILE,
                          FROM_HERE,
                          base::Bind(..., skip_dir_check, ...));
}</code>
V614 Potentially uninitialized variable 'skip_dir_check' used. Consider checking the fifth actual argument of the 'Bind' function. save_package.cc 1326

Переменная 'skip_dir_check' может остаться неинициализированной.

Замеченное N10 — выравнивание кода не соответствует логике его работы
<code class="cpp">void OnTraceNotification(int notification) {
  if (notification & TraceLog::EVENT_WATCH_NOTIFICATION)
    ++event_watch_notification_;
    notifications_received_ |= notification;
}</code>
V640 The code's operational logic does not correspond with its formatting. The statement is indented to the right, but it is always executed. It is possible that curly brackets are missing. trace_event_unittest.cc 57

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

Вот ещё пара мест с ОЧЕНЬ подозрительным выравниванием кода:
  • nss_memio.c 152
  • nss_memio.c 184

Замеченное N11 — проверка указателя после new
Во многих программах живет старый унаследованный код, написанный ещё в те времена, когда оператор 'new' не кидал исключение. Раньше в случае нехватки памяти он возвращал нулевой указатель.

Chromium в этом плане не исключение, и в нем встречаются такие проверки. Беда не в том, что выполняется бессмысленная проверка. Опасно, что при нулевом указателе раньше должны были выполняться какие-то действия или функции должны возвращать определенные значения. Теперь из-за генерации исключения логика работы изменилась. Код, который должен был получить управление при ошибке выделения памяти, теперь бездействует.

Рассмотрим пример:
<code class="cpp">static base::DictionaryValue* GetDictValueStats(
    const webrtc::StatsReport& report)
{
  ....
  DictionaryValue* dict = new base::DictionaryValue();
  if (!dict)
    return NULL;

  dict->SetDouble("timestamp", report.timestamp);

  base::ListValue* values = new base::ListValue();
  if (!values) {
    delete dict;
    return NULL;
  }
  ....
}</code>
V668 There is no sense in testing the 'dict' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. peer_connection_tracker.cc 164

V668 There is no sense in testing the 'values' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. peer_connection_tracker.cc 169

Первая проверка «if (!dict) return NULL;» скорее всего вреда не принесёт. А вот со второй проверкой дело обстоит хуже. Если при создании объекта с помощью «new base::ListValue()» не удастся выделить память, то будет сгенерировано исключение 'std::bad_alloc'. На этом работа функции GetDictValueStats() завершится.

В результате, вот этот код:
<code class="cpp">if (!values) {
  delete dict;
  return NULL;
}</code>
никогда не уничтожит объект, адрес которого хранится в переменной 'dict'.

Правильным решением здесь будет проведение рефакторинга кода и использование умных указателей (smart pointers).

Рассмотрим другой фрагмент кода:
<code class="cpp">bool Target::Init() {
{
  ....
  ctx_ = new uint8_t[abi_->GetContextSize()];

  if (NULL == ctx_) {
    Destroy();
    return false;
  }
  ....
}</code>
V668 There is no sense in testing the 'ctx_' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. target.cc 73

В случае ошибки выделения памяти не будет вызвана функция Destroy().

Дальше писать про это не интересно. Я просто приведу список других замеченных мной потенциально опасных мест в коде:
  • 'data' pointer. target.cc 109
  • 'page_data' pointer. mock_printer.cc 229
  • 'module' pointer. pepper_entrypoints.cc 39
  • 'c_protocols' pointer. websocket.cc 44
  • 'type_enum' pointer. pin_base_win.cc 96
  • 'pin_enum' pointer. filter_base_win.cc 75
  • 'port_data'. port_monitor.cc 388
  • 'xcv_data' pointer. port_monitor.cc 552
  • 'monitor_data'. port_monitor.cc 625
  • 'sender_' pointer. crash_service.cc 221
  • 'cache' pointer. crash_cache.cc 269
  • 'current_browser' pointer. print_preview_dialog_controller.cc 403
  • 'udp_socket' pointer. network_stats.cc 212
  • 'popup_' pointer. try_chrome_dialog_view.cc 90

Замеченное N12 — тесты, которые плохо тестируют
Юнит тесты замечательная технология повышения качества программ. Однако сами тесты нередко содержат ошибки, в результате чего не выполняют свои функции. Писать тесты для тестов это конечно перебор. Помочь может статический анализ кода. Подробнее эту мысль я рассматривал в статье "Как статический анализ дополняет TDD".

Приведу некоторые примеры ошибок, встретившиеся мне в тестах для Chromium:
<code class="cpp">std::string TestAudioConfig::TestValidConfigs() {
  ....
  static const uint32_t kRequestFrameCounts[] = {
    PP_AUDIOMINSAMPLEFRAMECOUNT,
    PP_AUDIOMAXSAMPLEFRAMECOUNT,
    1024,
    2048,
    4096
  };
  ....
  for (size_t j = 0;
    j < sizeof(kRequestFrameCounts)/sizeof(kRequestFrameCounts);
    j++) {
  ....
}</code>
V501 There are identical sub-expressions 'sizeof (kRequestFrameCounts)' to the left and to the right of the '/' operator. test_audio_config.cc 56

В цикле выполнятся только один тест. Ошибка в том, что «sizeof(kRequestFrameCounts)/sizeof(kRequestFrameCounts)» равняется единице. Правильное выражение: «sizeof(kRequestFrameCounts)/sizeof(kRequestFrameCounts[0])».

Другой ошибочный тест:
<code class="cpp">void DiskCacheEntryTest::ExternalSyncIOBackground(....) {
  ....
  scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
  scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize2));
  ....
  EXPECT_EQ(0, memcmp(buffer2->data(), buffer2->data(), 10000));
  ....
}</code>
V549 The first argument of 'memcmp' function is equal to the second argument. entry_unittest.cc 393

Функция «memcmp()» сравнивает буфер сам с собой. В результате тест не выполняет требуемую проверку. Видимо, здесь должно быть:
<code class="cpp">EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), 10000));</code>
А вот тест, который может неожиданно сломать другие тесты:
<code class="cpp">static const int kNumPainters = 3;

static const struct {
  const char* name;
  GPUPainter* painter;
} painters[] = {
  { "CPU CSC + GPU Render", new CPUColorPainter() },
  { "GPU CSC/Render", new GPUColorWithLuminancePainter() },
};

int main(int argc, char** argv) {
  ....
  // Run GPU painter tests.
  for (int i = 0; i < kNumPainters; i++) {
    scoped_ptr<GPUPainter> painter(painters[i].painter);
  ....  
}</code>
V557 Array overrun is possible. The value of 'i' index could reach 2. shader_bench.cc 152

Возможно, раньше массив 'painters' состоял из трех элементов. Теперь их только два. А значение константы 'kNumPainters' осталось равно 3.

Некоторые другие места в тестах, которые, как мне кажется, заслуживают внимания:

V579 The string function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the second argument. syncable_unittest.cc 1790

V579 The string function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the second argument. syncable_unittest.cc 1800

V579 The string function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the second argument. syncable_unittest.cc 1810

V595 The 'browser' pointer was utilized before it was verified against nullptr. Check lines: 5489, 5493. testing_automation_provider.cc 5489

V595 The 'waiting_for_.get()' pointer was utilized before it was verified against nullptr. Check lines: 205, 222. downloads_api_unittest.cc 205

V595 The 'pNPWindow' pointer was utilized before it was verified against nullptr. Check lines: 34, 35. plugin_windowed_test.cc 34

V595 The 'pNPWindow' pointer was utilized before it was verified against nullptr. Check lines: 16, 20. plugin_window_size_test.cc 16

V595 The 'textfield_view_' pointer was utilized before it was verified against nullptr. Check lines: 182, 191. native_textfield_views_unittest.cc 182

V595 The 'message_loop_' pointer was utilized before it was verified against nullptr. Check lines: 53, 55. test_flash_message_loop.cc 53

Замеченное N13 — Функция с переменным количеством аргументов
Во всех программах, много дефектов встречается в коде, предназначенного для обработки ошибок и реакции на некорректные входные данные. Это обусловлено тем, что такие места сложно тестировать. И, как правило, они и не тестируются. В результате, при возникновении ошибки, программы начинают вести себя намного более причудливо, чем планировалось.

Пример:
<code class="cpp">DWORD GetLastError(VOID);

void TryOpenFile(wchar_t *path, FILE *output) {
  wchar_t path_expanded[MAX_PATH] = {0};
  DWORD size = ::ExpandEnvironmentStrings(
    path, path_expanded, MAX_PATH - 1);
  if (!size) {
    fprintf(output,
            "[ERROR] Cannot expand \"%S\". Error %S.\r\n",
            path, ::GetLastError());
  }
  ....
}</code>
V576 Incorrect format. Consider checking the fourth actual argument of the 'fprintf' function. The pointer to string of wchar_t type symbols is expected. fs.cc 17

Если переменная 'size' равна нулю, программа попытается записать в файл текстовое сообщение. Но это сообщение, скорее всего, будет содержать в конце биллиберду. Более того, этот код может привести к access violation.

Для записи использует функция fprintf(). Это функция не контролирует типы своих аргументов. Она ожидает, что последним аргументом должен быть указатель на строку. Но на самом деле, фактическим аргументом является число (код ошибки). Это число будет преобразован в адрес и как дальше поведёт себя программа, неизвестно.

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

Я отбросил очень многие фрагменты кода, которые как мне кажется, будут не очень интересны читателю. Приведу пару примеров для ясности.
<code class="cpp">bool ManagedUserService::UserMayLoad(
  const extensions::Extension* extension,
  string16* error) const
{
  if (extension_service &&
      extension_service->GetInstalledExtension(extension->id()))
    return true;

  if (extension) {
    bool was_installed_by_default =
      extension->was_installed_by_default();
    .....
  }
}</code>
V595 The 'extension' pointer was utilized before it was verified against nullptr. Check lines: 277, 280. managed_user_service.cc 277

В начале указатель 'extension' разыменовывается в выражении «extension->id()». Затем этот указатель проверяют на равенство нулю.

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

Вот ещё пример диагностики, которую я предпочёл не заметить:
<code class="cpp">bool WebMClusterParser::ParseBlock(....)
{
  int timecode = buf[1] << 8 | buf[2];
  ....
  if (timecode & 0x8000)
    timecode |= (-1 << 16);
  ....
}</code>
V610 Undefined behavior. Check the shift operator '<<. The left operand '-1' is negative. webm_cluster_parser.cc 217

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

О ложных срабатываниях
Мне часто задают вопрос:

В статьях вы очень ловко приводите примеры найденных ошибок. Но вы не говорите, каково общее количество выдаваемых сообщений. Часто статические анализаторы выдают очень много ложных срабатываний и среди них практически невозможно отыскать настоящие ошибки. Как дело обстоит с анализатором PVS-Studio?

И я всегда не знаю, что сходу ответить на этот вопрос. У меня есть два противоположных ответа: первый — много, второй — мало. Все зависит, как подойти к рассмотрению выданного списка сообщения. Сейчас на примере Chromium я попробую объяснить суть такой двойственности.

Анализатор PVS-Studio выдал 3582 предупреждений первого уровня (набор правил общего назначения GA). Это очень много. И в большинстве этих сообщений являются ложными. Если подойти «в лоб» и начать сразу просматривать весь список, то это очень быстро надоест. И впечатление будет ужасное. Одни сплошные однотипные ложные срабатывания. Ничего интересного не попадается. Плохой инструмент.

Ошибка такого пользователя в том, что не выполнена даже минимальная настройка инструмента. Да, мы стараемся сделать инструмент PVS-Studio таким, чтобы он работал сразу после установки. Мы стараемся, чтобы ничего не надо было настраивать. Человек должен просто проверить свой проект и изучить список выданных предупреждений.

Однако так не всегда получается. Так не получилось и с Chromium. Например, огромное количество ложных сообщений возникло из-за макроса 'DVLOG'. Этот макрос что-то логирует. Он написан хитро и PVS-Studio ошибочно посчитал, что в нем может быть ошибка. Поскольку, макрос очень активно используется, ложных сообщений получилось очень много. Можно сказать, что сколько раз используется макрос DVLOG, столько ложных предупреждений попадет в отчет. А именно, о макросе было выдано около 2300 ложных сообщений «V501 There are identical sub-expressions.....».

Можно подавить эти предупреждения, вписав в заголовочный файл, рядом с объявлением макроса, вот такой вот комментарий:

//-V:DVLOG:501

Смотрите, таким простым действием мы вычтем из 3582 сообщений, 2300 ложных. Мы сразу отсеяли 65% сообщений. И теперь нам не надо их зря просматривать.

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

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

Напутствие читателям
Пользуясь случаем, хочу передать привет родителям. Ой нет, это что-то не то. Пользуясь случаем, хочу передать привет программистам и напомнить, что:
  • Ответ на вопрос «Вы сообщили о найденных в проекте ошибках разработчикам?», находится в заметке "Ответы на вопросы, которые часто задают после прочтения наших статей".
  • С нами лучше всего связаться и задать вопросы, используя форму обратной связи на нашем сайте. Прошу не использовать для этого twitter, комментарии к статьям где-то на сторонних сайтах и так далее.
  • Приглашаю присоединиться к нашему твиттеру: @Code_Analysis. Я постоянно собираю и публикую интересные ссылки по тематике программирования и языку Си++.


Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Школа программистов HeadHunter 2013

Сегодня утром стартовал очередной, уже четвёртый по счёту набор в школу программистов HeadHunter.
Занятия будут проходить по вечерам, два раза в неделю с октября по апрель в московском офисе технического департамента, недалеко от метро Алексеевская. Преподаватели – наши специалисты, в числе которых blv, mikesub, tum0rc0re и ваш покорный слуга. Во время обучения студентам выплачивается ежемесячная стипендия – 15 тыс. рублей. Лучшим выпускникам будущей весной мы предложим присоединиться к нашей команде.

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



Новая Школа
Четвёртая школа программистов — это две школы в одной: школа фронтенд-разработки и школа разработки мобильных приложений. На сайте можно подать заявку на одно из этих направлений.

В рамках курса фронтенд-разработки преподаватели расскажут о современных веб-технологиях и их применении при создании высоконагруженных проектов, инструментах разработки, отладки, профилирования и тестирования клиентских веб-приложений. Также студенты прослушают лекции про использование Unix-систем и best practices в разработке. Отдельные лекции будут посвящены языку Python, который широко используется при разработке фронтенда hh.ru.

В курсе разработки мобильных приложений студенты узнают об архитектуре Android, создании универсальных и эффективных приложений, разработке пользовательских интерфейсов по гайдлайнам. Мобильные платформы — одно из ключевых направлений развития компании, и в этом году новое направление под чутким руководством нашего Android-гуру tum0rc0re будет целиком посвящёно разработке под мобильную ОС от Google.

Студентам обоих направлений мы прочитаем лекции про agile-методологии, контроль качества и тестирование, эффективное использование систем контроля версий, расскажем об архитектуре и эксплуатации высоконагруженных систем. Наши дизайнеры проведут несколько занятий и мастер-классов, посвящённых разработке пользовательских интерфейсов. Мы познакомим студентов с рабочим процессом в компании, чтобы в дальнейшем у тех из них, кто присоединится к нам, не было проблем с адаптацией.

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

На нашем сайте опубликована немного более подробная программа обучения.

Смена направлений обучения (раньше мы делали акцент, в основном, на серверсайд-разработчиков со знанием Java и Python) связана, прежде всего, с нуждами компании. Школа программистов давно стала своего рода кузницей кадров для HeadHunter.

Потенциальные ученики школы — это студенты последних курсов, недавние выпускники вузов, аспиранты. Для них это отличный шанс получить то, что в настоящее время не может дать ни один университет — реальную практику и опыт разработки сложных и высоконагруженных систем. За три года существования школы девять её выпускников были приглашены в HeadHunter и сейчас работают в самых разных командах: поиск, веб-сервисы, мобильный сайт, маркетинг, SRE.



Итоги набора-2012
В прошлом году заявки на поступление подали более 300 человек, каждый третий успешно решил тестовое задание и дошел до второго этапа. На собеседования в итоге мы пригласили более 60 человек, отобрав из них 12, которые и стали студентами.

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



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

Приём заявок уже открыт. Ждём вас в школе программистов HeadHunter и желаем всем удачи! С кем-то из читателей нашего блога, уверен, увидимся осенью на занятиях =)

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Esboza — векторный редактор online & фреймворк (Часть вторая)



Это продолжение предыдущей статьи. Когда я писал первую статью об «Esboza» в голове вертелось — «Почти всё готово, осталось немножко всякой фигни по мелочам». Прошло три года. Сейчас в голове — «Вот теперь точно почти всё готово!».



Несколько примеров для затравки.

Логотипы html5 и css3
ru.esboza.com/doc/94435279c4a2415cd1e334fd77fffe01/


ru.esboza.com/doc/94435279c4a2415cd1e334fd77fffe02/


Иконки приложений из iOS7
ru.esboza.com/doc/eeae83cb98a887f6f6867a0916a519d5/


ru.esboza.com/doc/eeae83cb98a887f6f6867a0916a519d6/


ru.esboza.com/doc/eeae83cb98a887f6f6867a0916a519d7/


Написал я этот пост, потому что хочу обсудить с вами назначение сервиса и паттерн его использования. По началу, как часто бывает, делал проект просто потому что мне нравился сам процесс, штырило, just for fun и тд. Сейчас, когда за спиной километры кода, я не совсем осознаю что получилось. Сейчас опишу функционал: заходишь на сайт, авторизуешься, в лк создаёшь документ, рисуешь например иконку, экспортируешь в png или svg, можно так же распечатать, можно отправить ссылку на документ коллегам, каждый документ можно обсуждать и лайкать, любой документ можно форкнуть. Вот теперь самый интересный вопрос, такой сервис вообще кому-нибудь нужен? Если, да, то прошу поделиться своими мыслями в комментариях или предложить свой сценарий использования.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Промдизайн для электроники: как разработать корпус устройства



Разработка корпуса — один из основных этапов создания продукта для рынка электроники. В руках промышленных дизайнеров сосредоточена большая власть и ответственность: именно они определяют внешний вид устройства, стремятся сделать его привлекательным, стильным и удобным.
 
Каждый день мы пользуемся результатами работы промдизайнеров: смартфонами, ноутбуками, ТВ-приставками, клавиатурами, мышками и другими устройствами. Посмотрим на процесс создания всех этих вещей изнутри и ответим на три самых распространенных вопроса, которые возникают в процессе реализации проектов по разработке корпуса для электроники:
  1. Промдизайн: что вообще скрывается под этим словом?
  2. Разработка дизайна и конструкции корпуса: из чего состоит проект?
  3. с промдизайнерами: как организовать сотрудничество и оценить результаты?

1. Промдизайнеры и графические дизайнеры. Отличия

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

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

2. Дизайн и конструкция корпуса: этапы разработки

Разработка корпуса для электронного устройства — это не только дизайн (эскизы, 3D-модели), но также разработка конструкции и документации для серийного производства. 
 
Как правило, проект по разработке дизайна включает следующие этапы: 
  1. Генерация идей и концептуальная проработка
  2. Разработка оригинального дизайна и конструкции 
  3. Выбор материалов для корпуса
  4. Создание прототипов и опытных образцов корпуса
  5. Постановка на производство
Начиная с эскизов и предпроектных исследований важно учитывать технологические и ценовые особенности будущего устройства, поэтому дизайнеры должны работать вместе с технологами и конструкторами, которые реализуют требования производства и оценивают себестоимость. 
 
Самая сложная и длительная часть работы — это предварительный анализ и разработка эскизного предложения (концепции). На этих этапах команда разработчиков решает следующие задачи:
  • Исследование. Промдизайнер собирает информацию и погружается в тему: анализирует лучший опыт отечественных и зарубежных компаний, которые проектировали аналогичные изделия; изучает конструкционные и отделочные материалы, оценивает рациональность их применения; определяет требования к будущему изделию (эргономические, функциональные, экономические).
  • Техническое задание. Далее по результатам исследований можно готовить ТЗ, в котором будут указаны эксплуатационные, технические и эстетические требования к изделию. Для создания конкурентоспособного продукта они должны быть на уровне или выше рыночных аналогов. Как правило, ТЗ составляется совместно с заказчиком, с учетом его пожеланий.
  • Генерация идеи. На этом этапе дизайнер ведет эскизный поиск: делает зарисовки на бумаге или графическом планшете. Источником его вдохновения является не только материал исследований и ТЗ, но также архитектура, графика, произведения искусства, природный мир. Какой-то элемент из этого списка может стать отправной точкой для последующего формообразования. В результате заказчик получает несколько концепций будущего дизайна.
  • Трехмерное моделирование и визуализация. Лучшие эскизные предложения промдизайнер создает в виде трехмерной модели будущего объекта, включая визуализацию и наложение текстур. Он также готовит итоговые файлы для согласования проекта с заказчиком: 3D-модели и фотореалистичные 2D-изображения. 
  • Разработка конструкции. На основе выбранного дизайна создается конструкция корпуса. Она учитывает возможностей производства, сборки и характеристики материалов. Этот этап выполняется в современных системах автоматизации проектных работ (САПР), таких как CREO (Pro/Engineer). 
 

3. Работа с промдизайнерами: ведение и сдача/приемка проекта

Дизайн-проектирование может начаться с разных этапов. В некоторых проектах заказчик знает только о технической начинке будущего устройства, тогда дизайн корпуса создается с нуля. Бывает, что заказчик предлагает дизайнерам готовую концепцию, которую нужно проанализировать и доработать.
 
В процессе работы с промдизайнерами полезно придерживаться следующих правил: 
  1. Делим проект на четкие этапы, с конкретными целями и задачами. Последовательно обсуждаем все предварительные результаты.
  2. Договариваемся о личных встречах или видеоконференциях, общение только через электронную почту или скайп менее продуктивно.
  3. Ставим цели: у всех участников проекта должно быть четкое понимание будущего устройства (целевая аудитория, функциональность, ценовая категория, себестоимость). Без этого дизайн разработать невозможно.
  4. Выбор дизайна лучше доверить мнению нескольких компетентных специалистов, для более объективной оценки. Мнение одного человека не всегда объективно. 
При оценке результатов работы дизайнера стоит обратить внимание на следующие характеристики:
  • Внешний вид корпуса. Формы, пропорции линий, цветовое решение — всё это должно соответствовать запросам потребителей.
  • Фирменный стиль. Дизайн должен соответствовать общей философии и политике компании.
  • Материалы и технологии производства. Выбранные материалы корпуса должны соответствовать требованиям к устройству, учитывать заданную себестоимость и возможности производства.
  • Практичность. Использование продукта должно быть безопасным, простым и интуитивно понятным.
  • Удобство сборки и обслуживания. Собираемость изделия должна быть проверена на прототипах, важно оценить возможности ремонта и технического обслуживания устройства.
Мы надеемся, что эти советы помогут вам запустить свой проект в области промдизайна и получить ожидаемый результат.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Возможности отправки заметок в Evernote по электронной почте

tips

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

Тема письма
Перед тем, как мы перейдем к рассказу об этих функциях, давайте вспомним об особенностях использования темы письма при отправке сообщений в Evernote.

Название заметки: начало темы письма станет названием заметки
Блокнот: используйте символ «@» и название блокнота, чтобы отправить заметку именно в конкретный блокнот
Метка: укажите подходящую метку (из имеющихся в вашем аккаунте) после символа «#», чтобы присвоить ее заметке

Новинка: установите напоминание
Если вы отправляете в Evernote важную заметку, на которую нужно обратить внимание или решить описанную там задачу к определенной дате, то стоит сразу присвоить ей напоминание. Его можно добавить, поставив «!» в теме письма. Вы можете указать дату напоминания следующим образом:

Определенная дата:! ГГГГ/ММ/ДД
Завтра: !tomorrow
В следующий вторник: !tuesday (вместо «tuesday» это может быть название любого дня недели на английском языке)

Собираем все вместе
Необходимо соблюдать определенный порядок элементов в теме письма. Тема должна выглядеть следующим образом: [название] [напоминание] [блокнот] [метка].

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

Дизайн сайта !friday @работа #проекты

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

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

Если вы используете почтовый сервис Gmail и браузер Chrome, мы предлагаем вам попробовать наш веб-клиппер. Теперь он позволяет копировать письма напрямую из Gmail в Evernote.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Основы программирования объектов Умного Дома в MajorDoMo

image

Система MajorDoMo объединяет в себе различные компоненты, действие многих из которых сопряжено с чтением либо изменением данных. Для организации эффективного обмена данными между частями системы была создана объектная модель. Данная модель во многом соответствует парадигме Объектно Ориентированного Программирования (ООП) и людям, знакомых с данной парадигмой, не составит труда разобраться в имеющейся модели. Однако, знание принципов ООП совсем не обязательно, т.к. встроенная в систему модель достаточно упрощённая и может применяться без глубокого знания какого-либо языка программирования или же в качестве первого шага обучения этой концепции. В статье описаны основные составляющие этой модели.

Часть 1. Теория.

Классы
Класс это описание основных свойств, которыми должны обладать все объекты, относящиеся к данному классу. Класс не является объектом и не может сам по себе содержать значения этих свойств, он лишь описывает признаки и варианты поведения объектов. Физическую аналогию можно представить на примере простой классификации — например, к классу «Двери» может принадлежать объект «Дверь в ванную комнату», при этом, «Двери» могут иметь описание свойства «Статус» (открыта дверь или закрыта), но непосредственное значение может быть установлено только для конкретного объекта, но не для класса.

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

Пример:
image

Объекты
Объект представляет собой состояние реального (или виртуального) объекта. Свойства объекта могут иметь конкретные значения (например «статус» ,«температура» и т.п.). Кроме того, в самом объекте могут быть заданы свойства, которые дополняют набор свойств класса, к которому объект относится. Так же, для объекта может быть задана собственная реализация методов, описанных в классе.

Пример:
image

Объект, относящийся к классу, который, в свою очередь, является подклассом, наследует свойства и методы всех родительских классов.

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

Пример (описание свойств класса объектов):
image

Пример (установка/чтение свойства объекта):
<code class="php">setGlobal('myObject.myProperty',12345);
$value=getGlobal('myObject.myProperty');</code>

Методы
Методы представляют собой описание возможных действий объекта (или действий над объектом). Возвращаясь к физической аналогии, можно указать, что класс «Двери» может иметь методы «Открыть» и «Закрыть», т.е. все объекты класса так же будут иметь этот метод и мы можем открыть дверь вызвав метод «Дверь в ванную комнату.Открыть». Сама реализация метода представляет собой сценарий на языке программирования PHP. В данном случае частью сценария может быть установка свойства «Статус» в состояние «Открыта».

Пример (метод объекта):
image

Пример (код метода):
<code class="php">if ($this->getProperty('status')) {
 say("Движение в гараже");
}</code>

Пример (вызов метода):
<code class="php">callMethod('myObject.myMethod',$params); // $params не обязательный массив параметров</code>

Часть 2. Практика.

Во второй части статьи я приведу пример «встраивания» реального оборудования в объектную систему MajorDoMo. В качестве примера оборудования я буду использовать компоненты системы nooLite, которая уже неоднократно была представлена на Хабре, поэтому в целом о возможностях этих компонентов многие знают. Все нижеописанные действия производятся в панели управления MajorDoMo в разделе Объекты без внесения изменений в исходный код или файлы конфигурации системы.

Итак, для примеров мы будем использовать:

  • Несколько исполнительных силовых модулей (обычный + регулируемый/диммируемый)
  • USB-передатчик для отправки сигналов

План по пунктам:
  1. Создаём абстрактные классы для наших задач
  2. Создаём более специфические классы для поддерживаемого оборудования
  3. Добавляем объекты
  4. Управляем!

Пункт 1

Будем отталкиваться от того, что в нашем Умном Доме часто будет возникать задача включения/выключения какого-либо оборудования, поэтому заведём на самом верхнем уровне класс Relays (Реле) со свойством status (1/0 — включено/выключено), а так же с методами turnOff, turnOn, switch и refresh.

Код метода turnOff (выключение устройства):
<code class="php">$this->setProperty("status",0);</code>

Код метода turnOn (включение устройства):
<code class="php">$this->setProperty("status",1);</code>

Код метода switch (переключение устройства):
<code class="php">$status=$this->getProperty("status");
if ($status) {
 $this->callMethod('turnOff');
} else {
 $this->callMethod('turnOn');
}</code>
Код метода refresh ( состояния устройства):
<code class="php">$status=$this->getProperty("status");
if ($status) {
 $this->callMethod('turnOn');
} else {
 $this->callMethod('turnOff');
}</code>

Будем считать, что это необходимый минимум, который будет присущ всем управляемым объектам.

Пункт 2

Далее, будем добавлять поддержку нужного нам оборудования nooLite через создание дочернего класса nooLite. Отличаться от родительского он будет специфическим свойством channel (канал управления исполнительным модулем). Кроме того, будет добавлен новый метод sendCommand (отправка команды) и переопределён код методов turnOff и turnOn.

Код нового метода sendCommand (отправка команды устройству Noolite):
<code class="php">$cmdline='"c:\Program Files\nooLite\nooLiteCMD.exe" -api '.$params['command'];
safe_exec($cmdline);</code>

Код переопределённого метода turnOff:
<code class="php">$this->setProperty("status",0);
$this->callMethod("sendCommand",array('command'=>'-off_ch'.$this->getProperty("channel")));</code>

Код переопределённого метода turnOn:
<code class="php">$this->setProperty("status",1);
$this->callMethod("sendCommand",array('command'=>'-on_ch'.$this->getProperty("channel")));</code>

Остальные методы мы не трогаем — они остаются без изменений и работают, как положено с новым классом (спасибо ООП!).

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

Пункт 3

Добавим объект noo1, указав в описании объекта, что это «Подсветка потолка в гостиной», перейдём в настройку его свойств и укажем значение свойства noo1.channel = 1, т.е. этот силовой модуль находится на первом канале управления.

Пункт 4

Теперь мы можем включать/выключать этот модуль из любого сценария следующим кодом:
<code class="php">callMethod('noo1.turnOn'); // включаем
callMethod('noo1.turnOff'); // выключаем</code>

Либо же прописать управление этим модулем из меню в таком виде:
image

Получив в результате вот такой элемент управления:
image

Закрепим усвоенное прохождением пунктов 2-4 для добавления ещё одного устройства — силовой блок nooLite с поддержкой диммирования.

Пункт 2.

От созданного выше класса nooLite создадим дочерний класс nooLiteDimmer, добавив в него дополнительное свойство brightness. Так же добавим новый метод dim и перепишем код методов refresh, turnOn, turnOff

Код нового метода dim:
<code class="php">if ($params['value']) {
 $this->setProperty("brightness",$params['value']);
 $this->callMethod("refresh");
}</code>

Код переопределённого метода refresh:
<code class="php">$value=$this->getProperty("brightness");
$this->callMethod("sendCommand",array('command'=>'-set_ch'.$this->getProperty("channel").' -'.$value));
if ($value>0) {
 $this->setProperty('status',1);
} else {
 $this->setProperty('status',0);
}</code>

Код переопределённого метода turnOff:
<code class="php">$this->setProperty("status",0);
$this->setProperty("brightness",0);
$this->callMethod("refresh");</code>

Код переопределённого метода turnOn:
<code class="php">$this->setProperty("status",1);
$this->setProperty("brightness",100);
$this->callMethod("refresh");</code>

Пункт 3.

Практически аналогичен предыдущему варианту — добавляем объект noo2, прописываем в свойствах канал управления (2). Объект готов.

Пункт 4.

Объектом noo2 можно управлять точно так же как и noo1, но кроме этого мы можем использовать метод dim для установки яркости:
<code class="php">callMethod('noo2.dim',array('value'=>50)); // устанавливаем яркость в 50%</code>

Для управления светильником в меню создадим следующий элемент:
image

Вид элемента управления для пользователя уже приведён выше в примере управления обычным силовым блоком.

В Ноотехнике имеется ещё вот такой трёхканальный диммер для управления RGB-подсветкой:

Его интеграцию я оставлю за кадром (или в качестве «домашнего задания», если угодно), но в результате несложных манипуляций, подобным описанным выше, можно получить вот такой интерфейс:
image

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

Кроме того, все имеющиеся , обеспечивающие связь системы с конкретными «железными» (и не очень) протоколами позволяют указывать «привязку» параметров поддерживаемого оборудования к свойствам либо методам определённых объектов, что позволяет на уровне объектов иметь актуальное состояние всех подключенных систем (SNMP, ZWave, 1-wire и прочее).

Ну и в самом конце мне хотелось бы сказать, что изучать многие вещи проще всего на примерах конкретных реализаций, для чего был запущен специальный проект CONNECT, с помощью которого можно обмениваться готовыми конфигурациями своего Умного Дома. На примере своего профиля я показываю используемые компоненты, конфигурацию меню управления, созданные сценарии, классы и объекты MajorDoMo. В профиле не публикуется информация о значениях свойств объектов и, разумеется, нет возможности управлять оборудованием — вся информация предоставляется только в ознакомительных целях.

Удачной автоматизации!

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Из песочницы] Хронометраж для любительских автогонок, гибкий и беспроводной

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

Самый простой способ — раздать судьям секундомеры и научить их вовремя нажимать кнопку Старт/стоп. Очевидны недостатки такого способа — невыносимая низкая точность и подозрения участников на ангажированность судей. Другой момент — при проведении любительского ралли 3й категории старт и финиш часто разнесены между собой, и замер времени осуществляется по «синхронизированным» судейским часам. На практике — это китайские будильники по 30 р, которые убегают друг от друга на несколько секунд за 10 минут.

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

Пример 1. Заезды на четверть мили (402м), он же – Дрэг-рейсинг. На старте устанавливается ИК створ с 2-я или 3-я парами лучей. На финише также устанавливается створ с парой лучей, — по одному лучу на каждую дорожку. К стартовому створу подключен стартовый светофор. По команде контроллера светофор начинает отсчет стартовой последовательности, после чего участники начинают заезд. Время отсчитывается с момента зажигания зеленого сигнала, до момента пересечения финишного створа.
Логика и структура работы такой системы очевидна. Небольшой минус – это полкилометра проводов, соединяющих стартовый и финишный створ.

Пример 2. Кольцевые гонки на время, так называемый Time Attack. Заезды по кольцу, одновременно на дистанции 2 участника. Результат заезда – это время прохождения круга участником, равное интервалу между последовательными прохождениями створа.
Тоже все очевидно. Минусы, виденной мной реализации:
— необходимость каждого участника проходить только «свой» створ, который указан ему при старте, иначе система неправильно считает время прохождения круга;
— в связи с предыдущим пунктом – нахождение части конструкции посередине полосы, что чревато последствиями – нередко наблюдались наезды на центральную стойку с выводом из строя системы;
— неустойчивость системы к ложным срабатываниям, если через створ прошел посторонний предмет, как то – сбитый конус, часть отвалившегося бампера и т.п. Такое срабатывание приводило к прекращению заезда, и повторному старту. А участник, ехал уже на «последние деньги», со стучащим мотором и стремился победить. Обидно, да.

Пример 3. Ралли-спринт, старт и финиш разнесены на приличное расстояние – порядка сотни-двух сотен метров, участники стартуют с интервалом 2-3 минуты, на дистанции может находиться до 7-10 машин одновременно, в зависимости от протяженности. Время прохождения дистанции замеряется по действиям двух судей – судья на старте дает стартовую отмашку в определенное время по часам, судья на финише – записывает время финиша по своим часам, по разнице показаний время идет в зачет.
Минусы такого способа хронометража – несинхронность часов на старте и на финише (как я у же писал – часто используются китайские будильники из ларька в переходе), и влияние человеческого фактора (судья на старте может выпустить машину раньше или позже, как и судья на финише может зафиксировать момент прохождения недостаточно точно).

На очередном мероприятии, наслушавшись жалоб участников и организаторов, мной было предложено собрать систему под «свои» требования, для использования на любительских автоспортивных соревнованиях.
Были сформированы требования к этой системе:
— Дешево. По словам организаторов, цена аренды полупрофессиональной системы доходит до 15 тыс. р. за день соревнований – явно не для энтузиастов такой вариант;
— Возможность адаптации к различным видам мероприятий – дрэг, кольцо, ралли-спринт и т.п.;
— Легкость в развертывании и транспортировке – минимум частей, проводов и прочих принадлежностей;
— Максимальная автоматизация процесса соревнований – подсчет времени, расстановка результатов и прочее.

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

Модульность системы заключается в создании независимых ИК-створов, которые можно размещать на дистанции в практически произвольной конфигурации, на старт, на финиш, на промежуточный финиш и т.п.
Каждый створ способен фиксировать время пересечения луча и передавать момент фиксации на центральный пульт (пульт реализован на ноутбуке). Момент фиксации представляет собой полную метку времени, включая год, месяц, число, время с точностью до 1 мс. Таким образом, имея в распоряжении информацию о моментах пересечения створа, мы можем алгоритмически реализовать практически любую схему заезда.
Единственное требование в таком варианте исполнения – это точная синхронизация створов между собой. Такая синхронизация осуществляется с помощью GPS приемника – они достаточно дешевы на текущий момент и просты в обращении. Точность синхронизации без применения специальных мер – до 1мкс.
На фото – опытная плата для створа, способного обрабатывать до 6 ИК-лучей одновременно, плюс управление стартовым светофором. Зачем 6 лучей? Объясню чуть позже.
image
image

В качестве детекторов ИК-излучения использованы приемники TSOP4038, которые позволяют принимать «непрерывный» модулированный луч, в отличие от приемников других серий, которые при подаче непрерывного луча просто «затыкаются» в результате срабатывания встроенной АРУ и перестают реагировать на какие либо действия с лучом. Для данного приемника необходима частота модуляции ИК-луча в 38 кГц, но опыт показал, что значение это достаточно условно, и частота модуляции от 32 до 45 кГц вполне подходит под задачи.

Излучающее устройство представляет собой светодиод TSAL6100, запитанный от генератора модулирующей частоты. И помещенный примерно в фокусе собирающей линзы.
Про излучатель остановлюсь подробнее. Как я писал ранее, плата на фото способна обрабатывать до 6 лучей одновременно. Это используется для выставления автомобиля на линию старта в заездах со светофором. Так называемые Pre-Stage, Stage и Start. Чтобы точно выставить автомобиль на линию старта, за 10-15 см от стартового луча расположен луч Stage. И при пересечении этого луча загорается индикатор Stage на светофоре, информирующий участника о нахождении на линии старта и готовности к заезду.

На первый взгляд ничего сложного в этом нет. Но как показала практика – нельзя расположить два светодиода просто на расстоянии 10-15 см и не засветить при этом «соседний» датчик. То есть задача – независимое распознавание двух лучей, идущих параллельно на расстоянии 10-15 см. Пути решения: «механический» — сфокусировать луч так, чтобы он засвечивал только свой датчик, «алгоритмический» — придумать что то еще.

Фокусировка луча с помощью линзы дает отличный результат, размер пятна не превышает 3-4 см на расстоянии 8 м, но есть одно «но» — попасть таким лучом в приемник – та еще задача, особенно когда луч не виден, а на улице примерно -25°С. И к тому же, такое прицеливание требует применения механизмов, реализующих вращение излучателя в двух плоскостях, что усложняет собственно конструкцию.

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

Третий вариант – разделить лучи иным способом. А именно – по времени. Так как у нас имеется на плате уже источник сигналов точного времени (GPS), то включая каждый луч только в «свой» момент времени, мы можем независимо оценивать наличие или отсутствие сигнала от каждого излучателя. Для этого в схему управления излучателями так же был установлен модуль GPS приемника, который обеспечивал синхронизацию сигналов между собой.

Такое решение позволило «расширить» луч, и наведение излучателя на приемник упростилось на порядок.
В качестве фокусирующей системы была использована половинка самого дешевого оптического прицела (цена прицела в районе 150-200р), при этом вторая половинка используется соотвественно для второго излучателя.

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

Вот как это примерно выглядит. Посередине — блок с приемниками и беспроводным модулем, по краям – излучатели.
image
Передача данных

В качестве беспроводной сети передачи данных решено было использовать нечто похожее на Zig-Bee, а именно – Xbee-Pro (собственно это ZigBee и есть, только с некоторыми вариациями). Такие модули позволяют развернуть сеть с минимальными затратами на программирование и конфигурацию – фактически они делают прозрачным канал связи от последовательного интерфейса передатчика до приемника, и обратно соответственно. Плюсом вариант исполнения Pro имеет увеличенную мощность передатчика, и, соответственно, дальность действия. На испытаниях удалось добиться устойчивой работы на 500м, с использованием стандартных антенн типа «штырь» производства D-Link для Wi-Fi роутеров.
Для передачи данных в компьютер был собран адаптер Xbee-Usb на модуле Xbee-Pro и микросхеме FTDI232.

Как это работает

В приемном блоке реализован непрерывный таймер, синхронизированный с помощью GPS – по сигналу приемника 1PPS перезапускается аппаратный таймер микроконтроллера, который обеспечивает отсчет долей секунды.
Сигналы от ИК-приемников заведены на внешние прерывания микроконтроллера. При прерывании луча происходит захват текущего значения времени и помещение этой «метки» в очередь на передачу на пульт.

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

На этом аппаратной части выполнена. Ее задача – засечь момент пересечения луча и передать эту метку на пульт.

Далее в зависимости от вида соревнований и конфигурации заезда в дело вступает программное обеспечение.
image

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

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

Для обеспечения автоматизации расчетов результатов, каждой метке времени назначается номер участника, прошедшего через створ. Такой вариант позволяет осуществлять хронометраж независимо от количества машин на треке одновременно и их взаимного расположения.
Единственный вариант когда система не сработает – это частичное перекрытие корпусов при прохождении через один створ.
После присвоения метке номера происходит пересчет результатов и итоговой таблицы, которая может быть выведена на отдельный большой монитор для зрителей.
Например так. Эта таблица обновляется сразу после прохождения участником финишного створа, реализуя, таким образом, «онлайн-трансляцию» результатов для зрителей :)

image

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

Разные модификации (в процессе эволюции) данной системы использовались в течение года на нескольких мероприятиях, как то — ледовые гонки с параллельным стартом, грунтовый спринт с интервальным стартом, кольцевые гонки «ТаймАттак». Система показала себя с хорошей стороны — компактность конструкции (комплект на один створ помещается в пакет из супермаркета) и простота в эксплуатации.

На прошедшем 27.07.2013 2м этапе «ТаймАттак» в Омске, был опробован вариант с выводом результатов на большой монитор (вернее телевизор :) ) в режиме реального времени. Зрители и участники соревнований остались довольны ).

Компоненты, из которых была собрана система:
— микрононтроллеры: ATMega8 (излучатели), ATMega128 (приемный блок)
— GPS модули: Quectel L10
— беспроводные модули: Xbee Pro 2
— приемники ИК: TSOP4038
— корпуса из ABS пластика
— подставки из металлолома

Итоги:
— точность измерения времени прохождения дистанции – не хуже 1мс (в программе округляется до 0,01с для удобства восприятия)
— время развертывания – 5-10 минут
— время работы от комплекта аккумуляторов – пока не определено, на сутки хватает точно, аккумуляторы – б/у 7А/ч от офисного ИБП.
— бюджет — примерно 5-6 тыс. р. если покупать детали самостоятельно, я использовал залежи хлама на рабочем месте?

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

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Взгляд на Tizen OS



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

Несколько недель назад kirikch уже выкладывал статью под названием Знакомство с Tizen, из нее вы можете узнать об особенностях архитектуры, взаимодействия софта с железом и о разработке под ОС. А моя задача показать как работает система, чем нравится, чем – нет. Так сказать, посмотреть на нее с высоты обычного юзера.

И, безусловно, необходимо уделить внимание ролику, так как демонстрацию работы системы нужно наблюдать в живую.



Интересно, что Tizen была установлена на деволепер-образце Samsung Galaxy S3, который называется Samsung RD-PQ. Он отличается от оригинальной модели тем, что у него квадратные углы.



Внутри, по всей видимости, все тоже самое. По крайней мере, там однозначно стоит ARM-чип.



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

Стоит вспомнить, какой была первая версия Tizen.



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

Начиная со второй версии видно, что направлена в русло готового рынка: iOS и Android. Но чем может стать Tizen? Соперником iOS/Android? Я уже говорил в ролике, что для этого необходима какая-то фишка, которой сейчас нет. Соперник Windows Phone? Возможно, но логика у этих ОС настолько разная, что на WP всегда будет спрос от энтузиастов. Хотя у Windows Phone есть Nokia, которая продолжает взрывать рынок камерофонов. Самый логичный вывод – Tizen придет на замену Bada, распространяясь на большом количестве дешевых устройств и, возможно, раз в год – на одном ключевом (прям как iPhone 5). Такая модель развития поможет поднять ОС на уровень хотя бы в 1% от общей составляющей мобильных ОС в мире.

Посмотрим. Посмотрим…

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Альфа и бета тестирование android приложений

До недавнего времени для тестирования своих приложений я использовал различные способы публикации, от простого выкладывания apk файла на хостинг до использования специализированных сайтов типа testflightapp.com или использование своих велосипедов.

В очередном обновлении Google Play Developer Console была добавлена возможность тестирования приложений на определенном круге пользователей.
Если раньше загрузка apk файла сразу приводила к публикации приложения, то теперь добавлены 2 промежуточных шага.



Посмотреть на Яндекс.Фотках

При загрузке очередной версии приложения мы выбираем раздел:
  • альфа тестирование
  • бета тестирование
  • продакшион

из альфа тестирование можно перевести в бета или сразу продакшион, из беты — в продакшион.

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

Чтобы стать тестировщиком, пользователю необходимо вступить в сообщество google+ созданное разработчиком (указывается в настройках приложения) и перейти по ссылке play.google.com/apps/testing/com.yourdomain.package

Посмотреть на Яндекс.Фотках

В данный момент у меня получается достаточно удобный сценарий работы над небольшим социальным приложением:
  1. Разработку и отладку я веду на одном устройстве под специальным аккаунтом.
  2. Заканчиваю работу над очередной фичей, отлаживаю на этом устройстве, публикую альфа версию в google play
  3. Некоторое количество моих устройств разного формата и версий android самостоятельно обновляются на версию
  4. В течении дня-двух все устройства тестируются
  5. Все работает, данная версия переходит в следующую стадию, профит.

Плюсы:
  • Удобное администрирование тестировщиков
  • Тестировщикам нет необходимости ставить галочку разрешающую установку приложений из Uknown sources, потенциальная угроза безопасности
  • Установка приложения из маркета для пользователя выглядит безопаснее, «солиднее»
  • Большая группа бета тестировщиков автоматически станет пользователями опубликованного приложения, плюс в статистику
  • штатный трекер ошибок, нет необходимости добавлять в приложения сторонние библиотеки

Минусы:
  • штатный трекер ошибок, медлительный и менее информативный


Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Перевод] Управление загрузкой изображений



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

Использование контейнера для каждого изображения

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

<code class="html"><div class="img_wrapper">
    <img src="comicbookguy.jpg" alt=""/>
</div>
</code>
С помощью контейнера можно контролировать соотношение сторон картинки, а также использовать индикатор загрузки, что очень удобно, если изображения тяжелые.

Например, чтобы задать соотношение сторон 4:3, можно использовать следующий CSS:

<code class="css">.img_wrapper{
    position: relative;
    padding-top: 75%;
    overflow: hidden;
}
 
.img_wrapper img{
    position: absolute;
    top: 0;
    width: 100%;
    opacity: 0;
}
</code>
Для того, чтобы изображение отображалось в браузере только после полной подгрузки, необходимо добавить событие onload для изображения и использовать JavaScript, который будет обрабатывать событие:

<code class="html"><div>
    <img src="comicbookguy.jpg" alt="" onload="imgLoaded(this)"/>
</div>
</code>
<code class="javascript">function imgLoaded(img){
    var $img = $(img);
 
    $img.parent().addClass('loaded');
};
</code>
Код функции внутри тега HEAD должен быть расположен в самом конце, после любого jQuery или другого плагина. После полной подгрузки изображения его необходимо показать на странице:

<code class="css">.img_wrapper.loaded img{
    opacity: 1;
}
</code>
Для эффекта плавного появления картинки можно использовать CSS3 transition:

<code class="css">.img_wrapper img{
    position: absolute;
    top: 0;
    width: 100%;
    opacity: 0;
 
    -webkit-transition: opacity 150ms;
    -moz-transition: opacity 150ms;
    -ms-transition: opacity 150ms;
    transition: opacity 150ms;
}
</code>
Живой пример этого способа можно посмотреть на Codepen.

Использование контейнера для множества изображений

Предыдущий способ хорошо подходит для отдельных изображений, а что если на странице их много, например галерея фотографий или слайдер? Подгружать сразу все нецелесообразно — картинки могут много весить. Для решения этой проблемы можно заставить JavaScript'ом загружать только нужные в данный момент времени изображения. Пример HTML-разметки для слайдшоу:

<code class="html"><div id="Slideshow">
    <img src="slide_1.jpg" alt="" onload="slideLoaded(this)" />
    <img src="slide_2.jpg" alt="" onload="slideLoaded(this)" />
    <img src="slide_3.jpg" alt="" onload="slideLoaded(this)" />
</div>
</code>
Используем функцию slideLoaded(), чтобы контролировать процесс:

<code class="javascript">function slideLoaded(img){
    var $img = $(img),
        $slideWrapper = $img.parent(),
        total = $slideWrapper.find('img').length,
        percentLoaded = null;
 
    $img.addClass('loaded');
 
    var loaded = $slideWrapper.find('.loaded').length;
 
    if(loaded == total){
        percentLoaded = 100;
        // INSTANTIATE PLUGIN
        $slideWrapper.easyFader();
    } else {
        // TRACK PROGRESS
        percentLoaded = loaded/total * 100;
    };
};
</code>
Подгруженным изображениям присваивается класс loaded, а также отображается общий прогресс. И снова, JavaScript должен быть помещен в конец тега HEAD, после всего остального.

Кэширование

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

<code class="html"><script>
    var heroArray = [
        '/uploads/hero_about.jpg',
        '/uploads/hero_history.jpg',
        '/uploads/hero_contact.jpg',
        '/uploads/hero_services.jpg'
    ]
</script>
</code>
Когда посетитель заходит на сайт, после загрузки главной страницы, начинают загружаться изображения в кэш. Для того, чтобы кэширование не мешало отображению текущего контента, необходимо функционал JavaScript добавить в событие window load:

<code class="javascript">function preCacheHeros(){
    $.each(heroArray, function(){
        var img = new Image();
        img.src = this;
    });
};
 
$(window).load(function(){
    preCacheHeros();
});
</code>
Такой способ улучшает удобство использования сайта, однако дает дополнительную нагрузку на сервер. Это нужно иметь в виду при внедрении подобного функционала. Кроме того, необходимо обязательно учитывать возможные пути посетителей на сайте и кэшировать изображения, расположенные на страницах, которые пользователь вероятнее всего посетит. Чтобы понять такие пути по сайту, необходимо анализировать статистику посещаемости.

Загрузка по событию

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

<code class="html"><div class="img_wrapper lazy_load">
    <img
        src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
        data-src="comicbookguy.jpg"
        alt="Comic Book Guy"
    />
</div>
</code>
Стоит заметить, что URL изображение задано в data-src, а не в src. Это необходимо, чтобы браузер не загружал картинку сразу. Вместо этого в src загружается прозрачный пиксель в GIF, заданный в base64, что уменьшает количество обращений к серверу.

Остается только при нужном событии изменить значение src на data-src. JavaScript позволяет загружать изображения постепенно:

<code class="javascript">function lazyLoad(){
    var $images = $('.lazy_load');
 
    $images.each(function(){
        var $img = $(this),
            src = $img.attr('data-src');
 
        $img
            .on('load',imgLoaded($img[0]))
            .attr('src',src);
    });
};
 
$(window).load(function(){
    lazyLoad();
};
</code>

Заключение

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

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Разработчики MMO «Starcraft Universe» вышли на Kickstarter



MMO-мод к Starcraft II, превращающий игру в открытый ММО-мир, возможно, станет реальностью быстрее, чем планировалось. Разработчики дополнения запустили компанию на Kickstarter, для того, чтобы получить средства для скорого выпуска своего проекта. При этом запрашиваемая сумма исчисляется не миллионами и даже не сотнями тысяч долларов. Разработчикам потребовалось всего 80 тысяч долларов США. При этом за пару дней уже собрано 10 тысяч долларов, так что кампания выглядит вполне реальной.

Разрабатывается мод Upheaval Arts, а распространяться будет через Battle.net от Blizzard. Для тех геймеров, кто уже приобрел Starcraft, мод будет бесплатным. Но, понятно, совсем без денег мод не сможет быть реализован.

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


Via kickstarter

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Образы Tizen SDK Live на базе Ubuntu

Привет, Хабравчане!

В последнее время тема Tizen вызывает всё больший интерес, но многих смущает процесс начальной установки Tizen SDK и настройки среды разработки. Для упрощения знакомства с Tizen SDK мы решили создать Tizen SDK Live образы на базе Ubuntu, Xubuntu и Lubuntu, которые представляют из себя образы ОС с уже установленным Tizen SDK.



Поэтому вооружайтесь флешками пошустрее и добро пожаловать под кат за инструкциями по созданию загрузочной флешки с Tizen SDK Live.

Итак, приступим.

Инструкция для обладателей ПК с ОС Windows
1. Скачиваем подходящий образ Tizen SDK Live. Их у нас 3 (и пока что все для x86):
2. Готовим флешку размером не менее 4 ГБ. Рекомендуем использовать флешку как можно более высокоскоростную. Форматируем её в FAT32.

3. Скачиваем и запускаем бесплатную утилиту Win32 Disk Imager: sourceforge.net/projects/win32diskimager/

4. Выбираем наш образ в соответствующем поле. Программа притворяется, что работает только с образами в формате .img, но при этом она прекрасно работает с образами формате .iso.

5. Выбираем букву флешки, которую мы хотим использовать для создания Tizen SDK Live. Должно получиться похоже на это:



6. Жмём «Write».

7. Дожидаемся окончания подготовки флешки.

8. Перезагружаем ПК, выбираем в BIOS загрузку с USB.

9. Авторизуемся в Tizen SDK Live систему с помощью следующих реквизитов:
логин: tizentest
пароль: tizentest

Инструкция для обладателей ПК с ОС Ubuntu
1. Скачиваем подходящий образ Tizen SDK Live. Их у нас 3 (и пока что все для x86):
2. Готовим флешку размером не менее 4 ГБ. Рекомендуем использовать флешку как можно более высокоскоростную. Форматируем её в FAT32.
3. Определяем device node для своей флешки запуском из консоли следующей команды:
sudo dmesg | tail -20

4. Определив device node (и проигнорировав номер, например, /dev/sdb, но не /dev/sdb1), отмонтируем устройство запуском следующей команды:
sudo umount /dev/devicenode


5. Наконец, выполняем команду:
sudo dd if=/path/to/downloaded.iso of=/dev/devicenode bs=1M

6. Дожидаемся окончания подготовки флешки (минут 5–10, при этом никакого вывода в консоль нет, пусть вас это не смущает).

7. Перезагружаем ПК, выбираем в BIOS загрузку с USB.

8. Авторизуемся в Tizen SDK Live систему с помощью следующих реквизитов:
логин: tizentest
пароль: tizentest

Инструкция для обладателей Mac OS X
1. Скачиваем подходящий образ Tizen SDK Live. Их у нас 3 (и пока что все для x86):

2. Готовим флешку размером не менее 4 ГБ. Рекомендуем использовать флешку как можно более высокоскоростную. Форматируем её в FAT32.

3. Конвертируем скачанный нами образ из формата .iso в формат .img, выполнив из консоли следующую команду:
hdiutil convert -fCL_Prefix_ormat UDRW -o ~/path/to/target ~/path/to/downloaded.iso


4. Не подключая флешку, получаем список устройств:
diskutil list

5. Подключаем устройство, снова получаем список устройств, определяя, таким образом, device node (например, /dev/disk2) нашей флешки:
diskutil list


6. Определив device node, отмонтируем устройство запуском следующей команды:
diskutil unmountDisk /dev/diskN

7. Наконец, выполняем команду:
sudo dd if=/path/to/target.dmg of=/dev/devicenode bs=1m


8. Дожидаемся окончания подготовки флешки (минут 5 – 10, при этом никакого вывода в консоль нет, пусть вас это не смущает).

9. Перезагружаем ПК, выбираем в BIOS загрузку с USB.

10. Авторизуемся в Tizen SDK Live систему с помощью следующих реквизитов:
логин: tizentest
пароль: tizentest

После выполнения всех инструкций систему с флешки можно установить на жёсткий диск. Для этого используем стандартные механизмы Ubuntu (Unity Launcher Panel -> Install Ubuntu), Xubuntu (Menu -> Settings Manager -> Install Xubuntu) или Lubuntu (Menu -> System Tools -> Install Lubuntu) — в зависимости от вашего выбора. Единственное ограничение: независимо от того, какого пользователя вы выберете при установке системы на жёсткий диск, после установки будет доступен единственный пользователь: всё тот же пользователь tizentest с таким же паролем.

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

Версия Ubuntu, Xubuntu и Lubuntu: 13.04.
Версия Tizen SDK: 2.2.

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

Желаем успехов в изучении и ждём ваших отзывов! Отзывы и пожелания можно присылать на электронный адрес: dev.cis@samsung.com.

Также мы (команда Tizen Eva Group компании Samsung Electronics Russia) благодарим менеджера российского сообщества Tizen компании Intel Кирилла Чувилина за регулярное тесное сотрудничество и помощь в подготовке образов.

Скриншоты:

Ubuntu



Xubuntu



Lubuntu




Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Скромное обаяние — обзор Sony Xperia L

Выражение “бюджетный смартфон” у многих ассоциируется с неудобным и маломощным устройством, которое годится только для звонков и переписки. До недавних пор тем, кто не желают выкладывать за телефон крупную сумму было не так уж просто найти что-нибудь достойное и, в большинстве случаев, приходилось довольствоваться маленькими экранами, скромными камерами, жесткими ограничениями в плане использования приложений и игр. Sony Xperia L вполне укладывается в скромный бюджет, однако не может пожаловаться на низкую производительность, обладает большим экраном и изрядным набором современных технологий. Предлагаем вашему вниманию этого аппарата!





Комплектация и внешний вид

Комплектация довольно лаконичная, сделано это во имя экономии. В коробке находится телефон, батарея и зарядное устройство. Гарнитура, док-станция, NFC-метки и прочие аксессуары в комплект не входят.





При первом взгляде на Xperia L в голову сразу приходит мысль — да это же старый-добрый Arc S! Только со скошенными торцами, без кнопок под дисплеем и с меньшим количеством разъемов. Тактильные ощущения тоже очень схожие — телефон такой же тонкий и легкий, правда корпус не глянцевый, а из матового пластика (что даже лучше — не будет так царапаться). Над экраном расположен датчик приближения и фронтальная камера, слева — разъем miniUSB, справа — кнопка включения, кнопка управления камерой и регулятор громкости, а в середине верхнего торца — 3.5-мм разъем для гарнитуры. Заднюю часть украшает большой глазок основной камеры, LED-вспышка и внешний динамик. По кромке корпуса расположена хромированная полоска, отделяющая заднюю крышку, снять которую можно при помощи специальной выемки рядом с USB-портом. Кстати, держится крышка очень плотно и крепко, так что потребуются некоторые усилия, зато уж точно никто не будет жаловаться на зазоры или люфт. В нижней части окантовки спрятан индикатор, который умеет менять цвета в зависимости от назначенных на него событий или изображения на экране (например обложки альбома, фотографии или видео — в общем, как полоска у Xperia SP, только не такой большой). Аппарат выпускается в черном, белом и красном вариантах.





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



Экран
Экран у Xperia L 4.3-дюймовый с разрешением 480х854, за счет этого L-ка может похвастаться весьма достойной, для своего ценового сегмента, производительностью. На углы обзора и яркость жаловаться не приходится — при повороте меньше, чем на 60 градусов изображение даже не тускнеет и даже при 85 его вполне можно разглядеть. Как и у других моделей, экран сразу покрыт качественной пленкой, от которой, при желании, можно легко избавиться.

Камера
В этой модели установлен все тот же восьмимегапиксельный модуль Exmor RS, что и в Xperia SP, камера снабжена собственной кнопкой, позволяющей, в зависимости от настроек, либо запустить ее, либо сразу сделать снимок или начать съемку видео, либо ничего не сделать. В отличии от старших моделей, здесь нет суперавтоматического режима, зато присутствуют все остальные функции, такие, как HDR, панорамы, настройка экспозиции, баланса белого, фокусировки и чувствительности, стабилизатор изображения, распознавание улыбки, геотэги и графические фильтры, работающе в реальном времени. Видео записывается в формате HD с возможностью делать одномегапиксельные снимки во время записи при помощи специальной кнопки.













Производительность
Еще год назад трудно было представить двухъядерный процессор и гигабайт ОЗУ в бюджетном смартфоне, сегодня же это встречается все чаще. Как уже говорилось, за счет не самого высокого разрешения экрана производительность Xperia L достаточно высока и вполне достаточна для удобной работе в любых приложениях. С играми аппарат тоже справляется неплохо, в том числе и с достаточно прожорливыми трехмерными типа гонок или портов с PC (так, например, GTA 3 работает вполне шустро). 3DMark выдает вполне приемлемые 19-25 FPS. С результатами остальных тестов вы можете ознакомиться на скриншотах, приведенных ниже.









Батарея
Емкость батареи у L несколько ниже, чем у рекордсменов SP и ZR, однако не такая высокая мощность и прожорливость позволяет ей спокойно жить трое-четверо суток в режиме ожидания и около суток при интенсивном использовании — использовании 3G, Wi-Fi, GPS, чтении, фотосъемке, просмотре видео, прослушивании музыки, отправке SMS и разговорах по телефону. В интернете встречается информация о том, что некоторые энтузиасты умудрялись заставить Xperia L продержаться на одном заряде неделю. Кроме того, можно держать при себе запасную батарею или поискать аккумулятор повышенной емкости (правда, в последнем случае, компания Sony не несет ответственности за работоспособность аппарата).



Связь
Xperia L поддерживает все приличествующие современному смартфону стандарты связи, кроме LTE — за этим, все же, стоит обратиться к старшим моделям. За две недели активного использования связь ни разу не пропадала, все звонки проходили, Wi-Fi не отваливался, навигация работала идеально.

Софт и мультимедиа
По умолчанию здесь, как и у других моделей этого года, установлена операционная система Android 4.1.2 Jelly Bean с привычной оболочкой и набором тем. Набор предустановленного софта, в отличие от старших моделей, ограничен бесплатными приложениями: File Commander, Facebook, Opera Mini, NeoReader, OfficeSuite,, а также стандартный набор приложений от Google. Про фирменный плеер Walkman мы уже неоднократно рассказывали, а версия, установленная на Xperia L ничем не отличается от остальных. Среди интересных опций можно отметить уже привычные Throw (воспроизведение контента со смартфона на других устройствах, например телевизорах), передача данных через NFC с помощью функции Android Beam, режим STAMINA, позволяющий увеличить время работы от батареи в несколько раз за счет ограничения сетевой активности в режиме ожидания, возможность включать Wi-Fi при появлении в определенных местах, а также неплохой набор виджетов вроде плеера, прогноза погоды или быстрого включения/выключения Wi-Fi, Bluetooth и других функций.

Резюме
Удобный телефон с изящным дизайном по доступной цене. Большой экран, хорошая камера, солидное время работы от батареи и достаточная для подавляющего большинства задач производительность делают его отличным вариантом для тех, кто привык считать деньги, но предпочитает качественные и удобные вещи. Кроме того, приятно за такие скромные деньги получить устройство, не уступающее, а, во многом превосходящее позавчерашние флагманы.

Характеристики
Процессор: двухъядерный Qualcomm MSM8230, 1000 МГц
Память: 1 гб оперативной памяти, 8 мб встроенной, поддержка SD-карт
Видео: Adreno 305
Связь: GSM 900/1800/1900, 3G
Навигация: GPS, ГЛОНАСС
Основная камера: Exmor RS 8 мп
Фронтальная камера: 0,3 мп
Батарея: 1750 мАч, съемная
ОС: Android 4.1
Габариты: 128,7 x 65 x 9,7 мм
Вес: 137 г

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Метрика #18 — Подкаст о технологиях и проектировании интерфейсов и сервисов

Всем привет! С вами «Метрика» — шоу для тех, кто создает и анализирует продукты и сервисы, проектирует и руководит, занимается бизнесом и любит новые технологии.

Сегодня в программе

В 18-м выпуске Метрики вместе с Юрием Ветровым (jvetrau) мы продолжаем обсуждение iOS 7 — новой ОС для мобильных устройств от Apple. Сегодня мы представляем вашему вниманию третью, заключительную часть беседы.


Предыдущие выпуски (#1, #2, #3, #4, #5, #6, #7, #8, #9,#10, #11, #12, #13, #14, #15, #16, #17).

Заметки

Твиттер Платона
Твиттер Димы
Твиттер Юрия Ветрова
Реализм, скевоморфизм, флэт с Сашей Гриф
Принципы плоского дизайна с DesignModo
Статья от TheNextWeb по iOS 7
Статья от ReadWrite.com по iOS 7
Visual Assets Guidelines от Google — часть 1
Visual Assets Guidelines от Google — часть 2
Разбор приложения для подкастов на iOS от The Industry
Разбор приложения для подкастов на iOS от The Verge
Статья относительно возможностей iOS 7 для разработчиков от IteratingFun
Еще одна статья относительно возможностей iOS 7 для разработчиков от Techcrunch
И еще одна статья на MacRadar — рассуждения Марко Армента о предоставившейся возможности показать себя
iDownloadBlog о новой должности Джонни Айва и его позициях в компании Apple

Метрика в iTunes Store
RSS

Слушать подкаст
Скачать подкаст


Источник: habrahabr.ru,
получено с помощью rss-farm.ru


NASA собирается исследовать возможность добычи полезных ископаемых на астероидах



О добыче полезных ископаемых на астероидах на Хабре уже писали, и не раз. И действительно, тема интересная — ведь на Земле полезные ископаемые истощаются, притом очень быстро, и, к сожалению, большинство ресурсов является исчерпаемыми. Поэтому уже давно некоторые специалисты говорят о необходимости разворачивания проектов добычи ископаемых в космосе, в частности, на астероидах. Для проверки возможности добычи полезных ископаемых в космических условиях NASA собирается запустить космический аппарат, цель которого — анализ состава наиболее обычного астероида. «Астероидная миссия» должна начаться в 2016 году — именно тогда планируется запуск аппарата.

Сейчас ученых больше всего интересует две разновидности астероидов: «водные» и «металлические», или, на худой конец, каменно-металлические.

«Водные»: такие астероиды содержат большое количество воды. Они, в общем-то, бесполезны для землян, но могут быть чрезвычайно ценным ресурсом для будущих космических колонистов. Ведь одного «водного» астероида может хватить на долгие-долгие годы снабжения космической колонии. Такой тип астероидов является наиболее распространенным, «водных» астероидов около 75% в нашей Солнечной Системе.

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

Миссия NASA

Так вот, для подробного изучения состава одного из астероидов (Bennu) NASA запускает аппарат OSIRIS-REx. Запуск запланирован на 2016 год. Этот апарат будет оснащен тремя спектрометрами и прочим оборудованием, которое очень пригодится устройству в 2018 году, именно тогда планируется посадка на астероид.

Первый спектрометр, инфракрасный (OVIRS) поможет обнаружить органические вещества, если таковые будут. Кроме того, будет подробно изучен видимый и инфракрасный спектр астероида.

Второй спектрометр, Thermal Emission Spectrometer (OTES), попробует определить состав астероида, плюс определит его температуру.

И наконец, Regolith X-ray Imaging Spectrometer подробно изучит ту сторону космического тела, которая обращена к Солнцу. Это позволит ученым понять, какие вещества содержатся в приповерхностных слоях астероида.

Камеры, установленные на устройство, сфотографируют поверхность космического тела, после чего снимки отправятся на Землю. Из этих снимков ученые составят 3D модель астероида.

Кроме всего прочего, OSIRIS-REx соберет образцы материалов астероида, и доставит их на Землю. Ученые верят, что все это поможет определить состав типичного астероида, после чего можно будет уже обоснованно рассуждать, можно ли открывать сезон «космических старателей», или это — просто неосуществимая мечта.

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


Via NASA

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Релиз SDL 2.0

imageПосле нескольких лет разработки наконец-то состоялся релиз библиотеки SDL 2.0.0. Слухи о разработке второй версии SDL шли уже давно, но обширный список нововведений отчасти объясняет столь долгую разработку.

Библиотека SDL предоставляет такие средства, как быстрый вывод 2D-графики, обработку ввода, проигрывание звука, вывод 3D через OpenGL и другие операции, причем делает это кросплатформенно. Список платформ обширный: Linux, Windows, Windows CE, BeOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX и QNX — и вдобавок есть неофициальные порты на другие системы.

Сама библиотека написана на C и поддерживает C++, однако есть биндинги к большинству популярных языков. Автор libsdl был нанят компанией Valve, программные продукты которой активно используют библиотеку. К тому же, теперь библиотека выходит под лицензией zlib, а не LGPLv2, как было раньше, и SDL 2.0 можно использовать в любых своих приложениях — хотя вполне возможно, что сделано это было для того, чтобы Valve смогла включить ее в Steam для Linux.

Список изменений:
  • Полная поддержка средств 3D-акселерации;
  • Поддержка OpenGL 3.0+;
  • Поддержка OpenGL ES;
  • Поддержка многооконного режима и нескольких дисплеев;
  • Поддержка нескольких звуковых устройств (плюс поддержка вывода звука в формате 7.1);
  • Android и iOS;
  • API для поддержки Multi-touch;
  • Простое API для 2D рендеринга с использованием Direct3D, OpenGL, OpenGL ES;
  • Поддержка API отдачи (force feedback) для джойстиков;
  • Управление энергопотреблением;
  • Поддержка XInput и XAudio2 в Windows
  • Улучшенная многопоточность;
  • Убрано все, что раздражало в версии 1.2;
  • Многое другое.
Версией 2.0 еще с релиз-кандидата, вышедшего в июне, уже пользуются некоторые инди-разработчики и проекты OpenSource. Valve использует SDL 2.0 для поддержки игровых контроллеров и для ряда других применений.

Загрузить: SDL 2.0.0
Руководство по миграции на версию 2.0: Migration Guide
Подробная документация (wiki): wiki.libsdl.org/
Let's Make An RPG (C++/SDL2) — Tutorials
Другие обновления: SDL_image / SDL_mixer / SDL_net / SDL_ttf

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Геолокационные игры — большой обзор

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


Компании
booyah
Booyah, о которых я нелестно отзывался год назад, начали исправляться. Уволив CEO-основателя, они выбрали стратегию копирования хитовых механик с мобильных игр и добавления геолокационных фишек. MyTown2 — стандартный ситибилдер с настоящими зданиями, No Zombies Allowed — стандартная игра в башню с аркадными миссиями на карте. Очевидно, что так не отбить $30млн инвестиций, но ребята хотя бы начали делать очень качественные и красивые продукты.

red robot

Red Robot выбрали другую стратегию. По сути выкинув все наработки первой игры, Life is Crime, они сделали ставку на технологическую платформу для игр, сделав свой собственный парсер данных и тайловый сервер для карт и стандартизировав API. Теперь они берут в сателлиты молодых мобильных разработчиков и их руками собираются делать много инновационных продуктов. Время покажет насколько это выигрышная идея, пока первые две игры от молодежи — Rescue Rush и Global Outbreak, — скорее похожи на обкатку технологий. А флагманская Life is Magic пока откровенно буксует.


PerBlue в ушедшем году выпустила два клона своей передовой ММОРПГ Parallel Kingdom и публично объявила интересные цифры, о которых я писал в своем блоге по итогам поездки на конференцию GDC Online — $250k месячной выручки, 50.000 активная аудитория. Клоны ожидаемо не взлетели, а основной проект получил второе дыхание с запуском полетов на кораблях над картами реальных городов. Ставка компании на жанр «больших» ММО.


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

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


iOS


Управляемая жестами мобильная онлайн игра про захват настоящих городов. В мире идет конфликт двух сторон, постоянно поддерживаемый внутриигровыми событиями, турнирами и эпическими задачами. Очень стильный визуально проект, первым из всех геолокационных игр сделавший красивую трёхмерную карту (на основе OpenStreetMap, кстати). Проект, к сожалению, умирает, а что ему на смену выпустят разработчики пока неизвестно. Хранят молчание.


iOS / Android


Патриарх геолокационных игр, превращающих наш мир в одну большую ММОРПГ, чувствует себя неплохо. Совсем недавно в игре появились летающие корабли, открывая новую перспективу геймплея с картой мира. За прошедшие годы игроки понастроили множество городов, между которыми теперь идет экономическая война. Что примечательно, в Москве есть нефть :)


iOS / Android


Молодой претендент на роль самой реальной из ММОРПГ. Квесты теперь берутся на улицах настоящих городов, а инстансами становятся Южное Бутово и Гарлем. Фанфары пока можно убрать, невооруженным взглядом видны технические проблемы и нехватка контента, но концепция очень интересная.


iOS


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


Android


С одной стороны это геолокационная игра с жесткой привязкой к твоим координатам, что, как многократно проверено, epic fail. С другой — это Google, легко собравший на первое закрытое тестирование уже больше миллиона человек. Пока есть качественная оболочка и классный пиар, но нет глубокой и интересной игры. Будем следить во что Ingress превратится к релизу.


iOS


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

Тренды
Ничего не изменилось по сравнению с прошлым годом с плачевной монетизацией. По прежнему разработчики не научились зарабатывать ни на уникальных фишках геолокационных и социальных игр, ни даже простые и уже известные механики нормально перенести не смогли. Джастин из PerBlue с гордостью в голосе рассказывал, что 37% их выручки — это вечные микроаватарки. Что для нормального free2play — полный /facepalm и /epicfail.

Все еще основным рынком девелоперы выбирают США, а платформой — iOS. Альтернативные варианты пока что поле не паханное, Европой интересуются разе что финны из Grey Area (игра Shadow Cities), а достойный браузерный проект вообще один (Fleck). В Азии есть и аудитория и деньги, но пока очень мало проектов вообще, ни разработанных там, ни хорошо локализованных и запущенных. Главный успех — у Life is Crime с их соревнованием США vs Гонконг.

С небольшим перекосом в зомби, но геолокационные игры диверсифицируются по сеттингам, клоны мафии постепенно сдают позиции. Появились и «большие» фэнтези миры, и sci-fi, и казуальщина с большими головами, и военная тема. География также расширяется, и более чем отрадно, что отечественные разработчики вливаются в тренд. Первые ласточки — проекты Bigshot и Geopo.ly до наших дней не дожили, но на смену им пришли DigitWar и Город Героев. А грядущая CashSquare задолго до релиза уже была оценена в $4.5млн.

Геолокация стремительно захватывает рекламный и офферно/купонный рынок, в том числе в оффлайновом ритейле. Из нашей глубинки это незаметно, но в Сан-Франциско в шоппинг центре я лично видел не одного и не двух человек со смартфоном и запущенным Shopkick. Пока непонятно каким образом игры в этот поток вольются, но что вольются это точно — ведь рекламная волна несет миллиарды долларов.

Резюмируя: пока еще игры + геолокация = новый рынок. Он уже измеряется миллионами долларов, но пока еще микроскопический в общих масштабах и идеален для блицкрига. Списком игр-первопроходцев я с вами делюсь, пользуйтесь. Еще не поздно отправиться бороздить этот океан. А мы уже приступили :)

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Сеять/не сеять знания или стартаперы на вырост

image
На днях была встреча с Николаем Савиным, руководителем стартап-инкубатора GrowthUP. Хочу заметить, что такого рода встречи не проходят для меня впустую, — очень много полезного «мотаю на ус». Решил поделиться основными моментами встречи: тема разговора, ключевые вопросы, и на чем стоит остановиться подробнее. В конце кратко и сухо резюме всего написанного ниже.

На встречу я пришел с вопросом об украинском рынке образовательных услуг для стартаперов. И вот что получилось узнать.

Если представить стартап-предпринимателей Украины в виде пирамиды, то получатся следующие этажи сверху вниз:
1 — Серийные предприниматели
2 — Начинающие
3 — Наемные рабочие/менеджеры -> Решение стать предпринимателями
4 — Студенты/школьники

image
Рис. 1 — структура рынка стартап образования

Теперь кратко о каждом сегменте пирамиды.

1 — Уже успешные предприниматели, не раз запускавшие стартапы. Некоторые даже были успешно проданы.
Note: делятся опытом с 1 и 2-й категориями людей посредством личного блога, публикаций в прессе, постинга в соцсетях.

2 — Люди, которые приняли решение быть предпринимателями. Они склонны к самообразованию, читают тематические блоги, литературу, смотрят образовательные видео. Некоторые делают попытки создать что-то свое или присоединяются к другим стартапам.
Note: обращаются за помощью и советом к 1-й категории предпринимателей.

3 — Наемные работники, зачастую менеджеры, которые набираются опыта, присоединившись к уже успешным или растущим стартапам. Занимаются самообразованием, сами ищут тематическую информацию и осваивают ее, посещают курсы, лекции, семинары, вебинары.

Sum:
Численность 1+2+3 группы в сумме составляет в Украине порядка 10тыс. человек.
Для нас более всего интересна 4-я группа — студенты. С ними тяжелее всего работать, но их численность намного превышает первые три группы. При правильном подходе и попадании в целевую аудиторию можно добиться высокой конверсии и «посеять» будущее поколение предпринимателей, урожай из которых можно будет собрать уже через 2-3 года.

Итак, 4 группа — Студенты, которые еще не приняли окончательного решения быть предпринимателями. Они самые активные, гибкие и быстрообучаемые, и на них мы остановимся чуть подробнее.

image
Рис. 2 — четвертая категория Студенты и школьники

1 курс (школа): аудитория в этой группе не против разовых активностей, её легко собрать, и так же легко подбить на что-либо, а потом организовать. Но есть минус: активность данной аудитории достаточно нестабильная, ребят надо регулярно “шевелить” и давать “эмоциональные пендели”.
Главная стратегия — заставить задуматься о возможности быть предпринимателем. По ходу «созревания» часть аудитории отсеется.

2-3 курс: народ уже нагулялся, чему-то научился. Ко многим студентам пришло понимание, что поступили “не туда” или на на специальность, которая не нравится. Начинают задумываться о том, чтобы создать «что-то свое», некоторые даже создают.
Главная стратегия — воздействие на них через профоргов и лидеров студенческого мнения. Грамотно задавая вектор предпринимаемым усилиям, показывать возможности ИТ рынка (ЗП, языки, возможность учиться у лучших, заграница) и постепенно вербовать их волонтерами в инкубаторы и образовательные программы.

4-5 курс: более сознательные товарищи: они уже переходят от мыслей создать свое дело к действиям. Одна из мотиваций — закончится 5 курс и что потом: куда идти, где работать… Осмысленно пытаются найти свое место в жизни, на что и можно и нужно опираться.
Главная стратегия — проводить профориентацию, «скармливать» информацию об ИТ и стартапах, давать инструменты и знания, которые позволят приобрести навык делания стартапов и вызовут стремление начать действовать.

С какой стороны зайти или консервативные ректоры

Николай Савин делится тонкостями взаимодействия с университетами, набитыми шишками и полученным опытом в этом нелегком деле.
Первый подход — пойти напрямую к ректору, рассказать об образовательном проекте для предпринимателей в сфере технологического бизнеса (ИТ) и предложить взаимовыгодное сотрудничество.
Что можете услышать в ответ или диагноз:
  • если вуз столичный, то вежливо откажут, но презрительно сопроводят взглядом, мол, кто вы такие? Для таких консервативных людей важны корочки, дипломы, звания, а признают они только своих академических коллег. Ещё они упорно не могут (да и не хотят) понять, как может программист-самоучка зарабатывать больше денег, чем они.
  • если вуз региональный, то, скорее всего, руководство согласится сотрудничать. Причина: у них просто меньше бюджетных денег, поэтому готовы на любые бесплатные инициативы, взаимовыгодные сотрудничества и т.д.

Второй подход — пролоббировать подобные мероприятия через чиновников, которые так или иначе заинтересованы в PR своей личности на фоне разных образовательных программ.
Какой результат получите?
  • полный зал студентов и все хлопают, подарки, широкая огласка мероприятию во всех тематических СМИ, но… В результате имеем маленькую конверсию в заинтересованных людях, другими словами, «согнанный» полный зал не вашей целевой аудитории.
  • по сути, выигрывает только чиновник.

Третий подход — искать лидеров мнений среди студентов и работников вуза, лидеров организаций студ. самоуправления и обращаться к ним со своими проектами. Они с предложениями пойдут в ректорат.
Что получите в итоге, и почему это работает?
  • консервативная верхушка управления вузами всегда поощряет студ. инициативу. Если это преподносится правильно, инициативу одобряют, поддерживают и выделяют на ее осуществление нужные ресурсы.
  • вот работает и все:) Доказано опытным путем!

Хочется упомянуть о плюсах и минусах взаимодействия с представителями каждой категории пирамиды.
1-3 категории
плюсы:
+ легче работать
+ займет от 0,5 года
минусы:
— всего 10к в Украине (мало)
— большая конкуренция за их внимание
— есть свой опыт, в инструментах не нуждаются

4 категория
плюсы:
+ мало конкурентов
+ намного больше, чем 10к чел.
+ быстро обучаемые, гибкие, жажда знаний
минусы:
— маленькая конверсия
— «выращивание» займет от 2 лет

Сухо и сжато. Краткий итог сказанного выше

  • Весь опыт из статьи базируется на понимании украинского рынка (10тыс.= серийные+начинающие+менеджеры), но можно спроецировать с небольшой погрешностью на Россию и рунет в целом.
  • Нельзя «питаться» стартаперами и стартапами, не выращивая новых. Т.к. через пару лет аппетит у стартап-инкубаторов разгуляется, а качество знаний и навыков подрастающего поколения не успеет набрать нужных вершин. Если задумываться о перспективе, то нужно «сеять» знания, поливать и ждать 2-3 года урожая.
  • Проблема недостатка «правильных» предпринимателей существует, ангелы, инвесторы и инкубаторы о ней прекрасно знают и решают пока каждый сам за себя и разрозненными методами.
  • Студенты — самая интересная группа людей, взаимодействовать и влиять на которую пока тяжелей всего. Их уже пора заставить задуматься о жизни в качестве предпринимателей, дать необходимые знания, инструменты, приложить правильный вектор их развитию, не давать расфокусироваться… Нужно дать им время и ждать, что из этого выйдет.
  • От себя: у студентов (сам таким был) переизбыток энергии, желания делать бизнес, но никто не показывает им, как это делать. Но у них есть проблема с саморазвитием, “вилка” между поглощением тонн материала и фокусировкой на главных вещах. Прочесть и ознакомиться со всеми «важными» книгами по предпринимательству и продажам, статьям, видео, бесплатными курсами и т.д. — на это может уйти год времени и более, и это только изучение теории. Даже прочитав и “переварив” всё, студент всё равно не будет знать, что ему нужно использовать в данный момент.
Хочу поделиться причиной нашего интереса к рынку стартап образования — это наш проект getStart.me (ясли для начинающих предпринимателей).

image
Рис. 3 — “Золотое” кольцо стартапа, который в поисках бизнес модели

Цели нашего проекта = блог Grabli об ошибках предпринимателей + онлайн мастерская getStart создания проектов от идеи до прототипа.
1. Дать возможность учиться на опыте и ошибках других: собранные тематические статьи в одном блоге.
2. Помочь, направить и дать инструмент проверки проектов от идеи до прототипа, подкрепленный нужными на каждом этапе знаниями и инструментами, тем, кто решил ступить на путь ИТ предпринимательства.

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


Как вы видите идеальную систему образования из каких частей она должна состоять?


Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста. Проголосовал 1 человек. Воздержалось 2 человека. Источник: habrahabr.ru,
получено с помощью rss-farm.ru




Персонализированная. Формирование курса обучения происходит на основании входящих тестов.



Максимально концентрированная. Только «выжимки» материала, пошаговые инструкции.



Смешанные курсы. Теория онлайн и практика в оффлайн классах.



Преподаватели или наставники в этих курсах только практики. Делятся своим опытом.



Бесплатное для лучших студентов. Moneyback тем, кто набрал наивысший бал.



Сертификация, которую можно приложить к своим профайлам в соц. сетях (Linkedin, Facebook, etc.)



Обучение на реальных кейсах — case study.

Шестой «Фестиваль 404» состоится 12-13 октября 2013 в Самаре

12-13 октября 2013 уже в шестой раз в Самаре пройдет Фестиваль 404. Многие из вас уже успели побывать на нашем мероприятии, поэтому напишу сразу про новости. Во-первых, талисман феста Заяц Несудьбы теперь исполнен в актуальной сейчас акварельной технике.

image

Во-вторых, будет новое место для афтерпати, которое готовит массу сюрпризов даже для нас самих. В-третьих, в отеле Холидей Инн Самара, где проходит конференция, построили и открыли новый зал. А это значит, что мы запустим еще один поток и у нас появятся новые тематические секции: интернет-магазины, PR, и даже секция о медицине в интернете.


Мы очень ценим личное отношение, поэтому секции на Фестивале 404 будут традиционно авторские. Вот предварительный список секций и их ведущих:

  • Управление людьми (Сергей Котырев)
  • Медицина (Александр Щербина)
  • UX (Платон Днепровский)
  • PR / Digital / Кампании (Ася Ибрагимова)
  • Организация работы (Егор Гилёв)
  • Design Weekend (Артем Геллер, Вячеслав Правдзинский)
  • Интернет-магазины (Александр Кушпель)
  • Маркетинг для людей (Юрий Марин)
  • Мобильные приложения (Руслан Демьяненко)
  • Технологии (Александр Фитискин)
  • Стартапы (Антон Гугля)
  • Информационное общество (Денис Кортунов)

Всего за 2 дня конференции будет сделано более 60 докладов, среди которых ожидаются вот эти достойные бородатые джентельмены:

image

Мы ищем спонсоров и партнёров фестиваля. Можно быть спонсором, можно поставить стенд в холле, или просто штендер, можно еще что-то придумать. Спонсировать Фестиваль 404 — не только почетно, но и выгодно.

Теперь самое-самое важное. Если у вас нет сомнений и есть желание участвовать в фестивале, то до 15 августа вы сможете оплатить участие по специальной низкой цене для самых решительных. Приезжайте осенью в Самару на Фестиваль 404! Тут отлично.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


В Казанском ИТ-парке прошла экспертная сессия Russian Startup Rating

В минувшую субботу, 10 августа 2013 года в пресс-центре Казанского ИТ-парка прошла экспертная сессия Russian Startup Rating в Казани. Организатором и партнером мероприятия выступил Бизнес-инкубатор Казанского ИТ-парка. В ходе экспертной сессии оценивалась инвестиционная привлекательность стартап-проектов, представленных в двух основных направлениях: IT/Mobile и BioMed/Hi-Tech. Каждый эксперт оценивал проект по трем основным критериям – продукт, рынок и команда. В состав экспертов вошли:

Айдар Булатов, директор УК Bulatovgroup;
Михаил Корнеев, предприниматель, со-основатель проектов GreenfieldProject, OhMyMentor и сообщества MoscowDjango;
Михаил Казарцев, Управляющий партнер Фонда Посевных Инвестиций IT-Online-Venture;
Калаев Дмитрий, директор акселерационных и образовательных программ Фонда развития интернет-инициатив;
Василий Юзенчук, директор по маркетингу ГК ФИКС, консультант, тренер.

image

На суд экспертов было представлено 14 проектов:
RoadAR — all-in-one мобильное приложение для водителей.
Eleven — система перевода голосового звонка в текстовый лог.
Maidenly — проект в области e-commerce, в сфере подбора и продажи одежды для мусульман.
Feelfolio –онлайн-сервис психологической помощи
Luscinia – мобильное приложение, голосовой гид по культурно-историческим объектам туристических столиц мира.
Спикфон – система оповещения о чрезвычайных ситуациях через домофон.
Ennova – проект по созданию 3D-принтеров.
Трек Сервис – интеллектуальная система мониторинга транспорта.
Опт+Сервис – система учета для компаний занимающихся торговлей.
Телеучет – программный комплекс, предназначенный для организации центров сбора и обработки данных (ЦСОД) автоматизированных информационно-измерительных систем коммерческого учета мощности и электроэнергии, технического учета и контроля качества электроэнергии.
BestPediatr – единый городской конкурс «Мой любимый врач»
Columbis — Saas сервис для автоматизации работы туристических агентств.
Cafe4Me — Saas-сервис для онлайн предзаказа в кафе.
Avtozaper – система, облегчающая поиск и покупку автомобильных запчастей.

image

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

На экспертной сессии презентовали свои проекты из Казани и других городов России. Один из проектов его основатель презентовал при помощи Skype.

В ходе сессии Russian Startup Rating эксперты смогли ближе познакомиться с перспективными стартапами. Сами же начинающие предприниматели получили бесценный опыт общения с признанными профессионалами своей сферы.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Из песочницы] Три года и вагон шишек из жизни игрового стартапа

Вместо эпиграфа:
«План был рассчитан на 6 месяцев, и должен был подойти к финишу к маю этого года»

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

Начало
Моя история начинается в 2010 и захватит три с хвостом года. Я один из членов студии разработчиков видео игр Krealit базирующейся в Красноярске, зовут меня Дмитрий Дрыжак. Моя функция в коллективе сейчас сводится к работе со всей арт-частью, атмосферой, режиссурой, звуком, рутинным и не очень гейм дизайном, и чёрт знает, чем ещё. Сказанное уже само по себе намекает, какой характер носит наша работа. По образованию я архитектор, и началось всё с конца этого самого образования. Когда я выпускался из института, уже знал, что по специальности работать не хочу, так как наелся этой кухни — хотелось творчества, а не бесконечных расчётов, рабочки, пожарников, электриков и прочих сопутствующих вещей. Но проблема состояла в том, что, как тогда мне казалось, игровой индустрии у нас в городе в принципе нет никакой, и от безысходности я решил попробовать найти единомышленников. И нашел. Хотя в этом ничего удивительного не было, так как желающих делать игры всегда хватало. Удивительно и невероятно было то, что среди всех фигурировавших людей, а их было человек пятнадцать за всё время, нашлась пара людей, которые не только хотели делать игры, но при этом были способны их делать.

В общем, поехали…

Начали что-то делать. Тогда мы не имели ни малейшего представления о том, как этот процесс можно организовать, но настрой был чрезвычайно боевой. Фантазии о своих движках, ММО и грабеже караванов были отметены сразу по понятным причинам. Решили делать что-то типа Crimsonland, только в 3d — небольшой опыт на тот момент у меня был накоплен в процессе получения образования. Взяли движок Unity3d, в то время это было самое правильное решение. В качестве противников были выбраны… клоуны. Без всякого смысла, просто just for lulz, оттуда же в итоге вытек и сонно-бредовый сеттинг игры — в общем, отрывались, как могли.
Первые шаги, какими бы хилыми они ни были, невероятно воодушевляли, но, естественно, не всех — большая часть народа отвалилась сразу, кое-кого, даже, выпнули за деструктивную деятельность (впрочем, со многими из них остались хорошие, дружеские отношения, которые приносят плоды до сих пор). Но это всё естественная, не интересная и довольно унылая рутина, так что можно просто остановиться на том, что нас осталось четверо — я, Юля Прокшина — моя подруга и второй художник, и два программиста: Саша Липатов и Андрей Кривоносов. Примерно через три месяца у нас уже что-то ползало, что-то стреляло и, как-то, игралось. Сейчас, конечно, все это кажется нам страшно убогим, но тогда мы смотрели на свой продукт через розовые очки дилетантов и рвались в бой. Впереди грезились невероятные перспективы, и под это дело мы решили съехаться в одну квартиру, чтобы работа пошла ещё бойчее. Стоит упомянуть, что всё это время я работал в небольшой игровой фирме художником (внезапно появилось предложение, как раз когда мы начинали), а остальные доучивались по своим специальностям, так что на алтарь геймдева смело клали всё свободное время.

Первые урожай шишек
И вот, прошло полгода. Наступил момент, когда мы первый раз решили, что игра почти готова, и как раз в это время мы списались с компанией Sigma Team с предложением нас издавать. На что они согласились, приставили к нам человека с указанием, что игру надо сильно доделывать, внедрять какие-то фичи, и ещё непонятное чего-то там. Мы взялись за работу хотя и не так бодро, но всё же стойко. В качестве фичи выбрали возможность устанавливать башни, и вообще, запилить что-то типа tower defense, плюс добавить больше уровней, сеттингов, пушек, в общем, сделать всего много и лучше. Ещё полгода мы бултыхались с этим непонятным человеком, концентрация собираемых по дороге грабель хоть и снизилась с зашкаливающей в начале, но всё равно была высока, опыт лился рекой. Всё это, однако, без финансирования, на голом энтузиазме и в свободное время.

И вот, к августу 2011-го мы во второй раз решили, что игра почти совсем готова, и её надо выпускать ни больше, ни меньше — на Steam, и продавать. Непонятный человек сигнализировал директору Сигмы, чтобы тот посмотрел результат. Он посмотрел и сказал: «А теперь мы будем делать из этого игру». Мы были ошарашены, и, не долго думая, решили, что «это какая-то фигня» и «сколько можно доделывать» и сами запульнули игру на Steam, на ревью. Тряслись и ждали около трёх дней, после чего выяснилось, что нас отбрили. Первый раз у всех прошел холодок по спине, и первый раз показалось, что свет в конце туннеля начал тускнеть. Как бы то ни было, все собрались с духом, решили, что игру нужно просто как следует доделать и… начали доделывать. По ходу дела парни тоже устроились в местную фирму, а Юлик начала помогать мне с фрилансом, на который я, к тому времени, благополучно перешел с постоянного места работы.

Игру мы доделывали ни много, ни мало – год. Успели съездить на КРИ 2012, с чего поимели одно хорошее знакомство, которое в будущем сильно помогло, а также фотки с Виктором Зуевым и Георгием Добродеевым (всё предыдущее время с удовольствием слушали «Адову кухню» — отличный подкаст, очень жалко, что теперь закрыт). В процессе доделки ВНЕЗАПНО узнали, что, оказывается, в играх есть такие составляющие, как юзабилити, целеполагание и ещё много базовых штучек из гейм дизайна, казалось бы – вещи совершенно очевидные, но мы благополучно игнорировали их всё предыдущее время.

Второй урожай шишек. Релиз
И вот подкрался сентябрь, а вместе с ним и релиз. Как раз в это время на горизонте замаячили какие-то непонятные, вроде как, инвесторы, которые, вроде как, хотели дать денег. Перед релизом накал мозгов зашкаливал, пар шел из ушей, глаза то разбегались в стороны, то съезжались в кучу. В общем со скрипом, но игра таки появилась на сайте Сигмы, а потом и на других площадках. Ребёнка назвали «I am weapon». В спешном порядке начали клепать патчи, латать дыры, и хвататься за голову при каждом шорохе.

image

Тем временем мы начали уже плотно общаться с потенциальными инвесторами, которых привлекал факт того, что мы смогли, по крайней мере, доделать игру. Один из инвесторов появился благодаря тому самому знакомству на КРИ, другой – благодаря ещё более раннему знакомству на конференции местного масштаба (так что любые мероприятия посещать полезно). Условия предлагали практически идентичные, мы долго метались, не могли выбрать, но в итоге склонились к менее опытному в геймдеве, но более живому варианту. Но об этом чуть позже – релиз состоялся, и мы, затаив дыхание, ждали, что на нас сейчас польётся поток счастья и успеха… но нас ждал вместо этого былинный фэйл. Игра продавалась настолько плохо, что даже не верилось, что мы угробили на неё два с половиной года. Ко всему прочему вышло так, что мы отдали полный контроль над «I am weapon» издателю и, впоследствии, не могли никаким образом использовать ни кросс промоушен, ни какие-то ещё ходы связанные с этим продуктом. Позже мы пытались понять причины такого провала, и пришли к следующим выводам:

1) Никакой маркетинг – минимальное освещение в прессе, как следствие, низкий трафик на площадках.
2) Безобразная кода. Тогда она казалась в пределах разумного, но сейчас пришло понимание того, что игра такого типа не может столько грузиться, и так жрать ресурсы. Это, на мой взгляд, основная причина низкой конверсии.
3) Завышенный порог входа – в игре, с ходу, было очень трудно разобраться, плюс хелпов было неприлично много, навязчиво и непонятно. Юзабилити должно быть интуитивнее. Ещё один гвоздь в крышку гроба конверсии.
4) Направленность на узкую и не самую популярную платформу – PC. Я искренне люблю PC-гейминг, но как рынок для инди-игр, увы, это не самое лучшее место.

Итак, осознав всё это, мы начали вести диалог с инвестором. Как самое логичное решение, выбрали: использовать имеющиеся наработки, но внести ряд радикальных изменений. Во-первых платформа — было решено делать игру для мобилок. Во-вторых, что касается башен: чтобы уменьшить порог входа, было решено им отвести совсем второстепенную, опциональную роль. В-третьих – оптимизация, тут мне и Юле пришлось наступить себе на горло и сократить «полигональные амбиции», плюс оптимизация вообще всего, чего только можно — в начале разработки такое решение принять реально проще. В-четвёртых, заранее заложенный бюджет на маркетинг. В-пятых, знакомый массам, популярный сеттинг зомби апокалипсиса и говорящее название «Guns n Zombies». Далее был составлен дизайн документ в общих чертах, план работ, как мы его видели, расписанный по дням, и смета… И вот тут был первый пролёт в новом проекте. Мы решили перейти на полный рабочий день в уже свежеиспечённой фирме, и исходя из предполагаемых затрат нашего времени составляли смету. Вот только проблема была в том, что мы подсознательно вталкивали смету и план в предложенный бюджет, и напрочь забыли о таких вещах, как накладные расходы, аренда помещения и то, что сроки всегда умножаются на 3. Хотя, мы уже чуяли, что всё не так гладко, как кажется, и решили из 40 тыс. зарплаты тратить только половину, а ещё половину оставлять про запас.

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

Итак, на мысли о том, что мы все-таки получили инвестиции, и это уже не мало, доползли до апреля, когда стала выплывать на поверхность мысль о том, что денег как-то маловато. Тут же у Андрея возникла здравая мысль – запустить краудфандинговую кампанию на KickStarter. Начались сбор и подготовка материалов, налаживание контактов и прочие связанное с запуском кампании на КС. О нем вы можете прочитать и в других местах, например в группе на фэйсбуке «Русские на Кикстартере», если коротко, то «чего мы только не дали – только на ушах не стояли». Отдельно стоит упомянуть, что на КС мы выходили через Евгения Жукова – зарекомендовавшего себя человека. Помимо прочего он же помог нам с организацией части маркетинга, оформлением страницы и другими вещами.

image

Кампания была запущена, роды были не хуже первого релиза, сил и средств угроблено куча. И вот, мы плавно подошли к настоящему моменту, и ситуация совсем не радостная – компания на КС не дала почти никакого выхлопа. Хотя до завершения ещё и остались около десяти дней, но надежды почти нет. Причины в данный момент совершенно не понятны. То ли дело в летнем сезоне, когда все греют попу на югах и Кикстартер мало кого из журналистов интересует просто так, без серьёзных договорённостей заранее. То ли специфика КС и ориентированность на «в доску инди» и ПК, а не на мобильные игры. То ли у нас проект слишком доделанный. То ли, в конце концов, руки кривые, и игра – треш. Но, есть оптимистичное мнение, что даже такая кампания по сбору средств – неплохой анонс, так как есть публикации и видео обзоры, работа с комьюнити есть, демка выпущена и поиграна, и на том же Стиме, в гринлайте, отзывы не плохие и даже хорошие. Отдельно хотел бы отметить, что хейтеры и негативные отзывы были замечены только среди русских пользователей, комментарии в духе «соберут бабло и исчезнут!», что весьма огорчило. И ещё одна огромная ошибка всплыла на поверхность – с комьюнити надо было начинать работу сразу, как началась , трубить во все трубы и привлекать внимание, а мы зарылись в арт и код, и на всё и всех забили.

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

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

P.S. Всем спасибо за внимание! Любые комментарии, предложения, да вообще всё в адрес автора этой статьи и её предмета только приветствуется.

P.P.S. Ну а про KickStarter в пору писать отдельную статью, за которую я тоже постараюсь сесть уже после того, как кампанию закончим. Может в ней учту что-то, что посоветует уважаемое хабрасообщество.

UPD. Ссылка на наш проект на KickStarter: www.kickstarter.com/projects/715973196/gunsnzombies-apocalyptic-video-game?ref=search

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Из песочницы] Генераторы в действии

Небольшое вступление

Не так давно я решил для себя, что пора восполнить большой пробел в знаниях и решил прочитать про переходы между версиями , т.к. понимал, что остался где-то между 5.2 и 5.3 и этот пробел необходимо как-то устранить. До этого я читал про namespaces, traits и т.д, но дальше чтения не уходило. И вот тут я заметил генераторы, почитал документацию, одну изстатей на хабре на этот счет и после этого возникла мысль — а как раньше без них жили-то?

Данным переводом хочу помочь хотя бы новичкам, поскольку на php.net документация по генераторам на английском и, на мой взгляд, должным образом не раскрывает всю идею и места применения. Текста много, кода чуть меньше, картинок нет. Потребуются общие знания, например, про итераторы. Очевидный код комментировать не буду, а вот сложные для понимания примеры постараюсь объяснить в силу своих знаний.

Теория

Сразу скажу главную вещь — генераторы никоим образом не позволят сделать что-то новое, чего нельзя было сделать раньше, поскольку генераторов до PHP 5.5 нет. Это лишь новая возможность, которая несколько меняет обычное поведение языка. Везде, где используются генераторы, можно также использовать итераторы. Теперь, зная об этом, сразу взглянем на пример. Скажем, нам необходимо пройтись по строкам в файле. В процедурном стиле это можно сделать как-то так:

<code class="php">$f = fopen($file, 'r');
while ($line = fgets($f)) {
    doSomethingWithLine($line);
}
</code>

Это обычное решение, ничего странного тут нет. Но что если нам нужно что-то более абстрактное? Скажем, генерировать строки из абстрактного источника. Да, сегодня это может быть файл, но завтра мы решим, что более удачным решением будет база данных или вообще что-то иное.

Сейчас у нас есть два пути решения данной задачи — мы можем вернуть массив или итератор. Но возвращая массив есть несколько проблем: во-первых мы не знаем сколько нам нужно памяти (вдруг файл у нас размером 30 гб?), а во-вторых, возможно, мы и вовсе не сможем описать наш источник как массив (например, мы можем возвращать бесконечные порции данных и попробуй угадай когда этот поток закончится, если ты клиент).

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

<code class="php">class FileIterator implements Iterator {
    protected $f;
    public function __construct($file) {
        $this->f = fopen($file, 'r');
        if (!$this->f) throw new Exception();
    }
    public function current() {
        return fgets($this->f);
    }
    public function key() {
        return ftell($this->f);
    }
    public function next() {
    }
    public function rewind() {
        fseek($this->f, 0);
    }
    public function valid() {
        return !feof($this->f);
    }
}
</code>

Совсем просто, не так ли? Хорошо, не совсем, но уже что-то. Хотя если мы взглянем на пример внимательнее, то увидим, что мы не совсем точно описали итератор, поскольку двойной вызов метода current() не даст нам ожидаемый результат в виде одного и того же значения.
Я (автор статьи, не «переводчик») сделал это специально, чтобы показать, что замена процедуры на итератор не всегда является простой задачей, поскольку в реальных ситуациях все куда сложнее. Давайте сделаем правильный итератор для нашего файла.

<code class="php">class FileIterator implements Iterator {
    protected $f;
    protected $data;
    protected $key;
    public function __construct($file) {
        $this->f = fopen($file, 'r');
        if (!$this->f) throw new Exception();
    }
    public function __destruct() {
        fclose($this->f);
    }
    public function current() {
        return $this->data;
    }
    public function key() {
        return $this->key;
    }
    public function next() {
        $this->data = fgets($this->f);
        $this->key++;
    }
    public function rewind() {
        fseek($this->f, 0);
        $this->data = fgets($this->f);
        $this->key = 0;
    }
    public function valid() {
        return false !== $this->data;
    }
}
</code>

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

<code class="php">function getLines($file) {
    $f = fopen($file, 'r');
    if (!$f) throw new Exception();
    while ($line = fgets($f)) {          
        yield $line;
    }
    fclose($f);
}
</code>

Намного проще! Да, это почти как первый пример с функцией, только появилось исключение и ключевое слово yield.

Итак, как оно работает?

Очень важно понимать, что в примере выше изменяется возвращаемое значение функции. Это не null, как может показаться с первого взгляда. Наличие yield говорит о том, что PHP вернет нам специальный класс — генератор. Генератор ведет себя также, как и итератор, поскольку он реализует его. И использовать генератор можно аналогично итераторам.

<code class="php">foreach (getLines("someFile") as $line) {
    doSomethingWithLine($line);
}
</code>

Вся фишка здесь в том, что мы можем писать код как угодно и просто выбрасывать (yield, йелднуть, йелдануть… не знаю как перевести правильнее, когда есть бросание исключений) каждый раз новое значение когда нам это надо. Итак, как же оно работает? Когда мы вызываем функцию getLines(), PHP выполнит код до первой встречи ключевого слова yield, на котором он запомнит это значение и вернет генератор. Затем, будет вызов метода next() у генератора (который описан нами или итератором), PHP снова выполнит код, только начнет его не с самого начала, а начиная с прошлого значения, которое мы благополучно выбросили и забыли о нем, и опять, до следующего yield или же конца функции, или return. Зная этот алгоритм, теперь можно сделать полезный генератор:

<code class="php">function doStuff() {
    $last = 0;
    $current = 1;
    yield 1;                                               
    while (true) {                                     
        $current = $last + $current;
        $last = $current - $last;
        yield $current;                              
    }
}
</code>

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

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

Сложный пример

Нам нужно сделать собственный ArrayObject. Вместо того, чтобы делать итератор, сделаем небольшой трюк с генератором. Интерфейс IteratorAggregate требует от нас всего один метод — getIterator(). Так как генератор возвращает объект, реализующий итератор, то мы можем переопределить этот метод таким образом, чтобы он возвращал генератор. Все просто:

<code class="php">class ArrayObject implements IteratorAggregate {
    protected $array;
    public function __construct(array $array) {
        $this->array = $array;
    }
    public function getIterator() {
        foreach ($this->array as $key => $value) {
            yield $key => $value;
        }
    }
}
</code>

В точку! Теперь мы можем перебрать все свойства нашего массива через генератор или через обычный синтаксис обращения по ключу.

Отправляем данные обратно

Генераторы позволяют отправлять себе данные, используя метод send(). В некоторых случаях это может быть очень удобно. Например, когда надо сделать какой-то лог-файл. Вместо того, чтобы писать целый класс для него, можно просто воспользоваться генераторами:

<code class="php">function createLog($file) {
    $f = fopen($file, 'a');
    while (true) {          # да, опять бесконечный цикл;
        $line = yield;      # бесконечно "слушаем" метод send() для установки нового значения $line;
        fwrite($f, $line);
    }
}
$log = createLog($file);
$log->send("First");
$log->send("Second");
$log->send("Third");
</code>

Довольно просто и быстро. Чтобы немного усложнить задачу, посмотрим пример, где функции работают совместно, перекидывая управление между собой при помощи генераторов. Нам нужно построить очередь, которая получает и отправляет данные пакетами. Иногда такие задачи появляются, когда мы читаем бинарный поток и нужно контролировать размер пакета.

<code class="php">function fetchBytesFromFile($file) {           # функция возвращает генератор, который считывает данные разной длины из файла
    $length = yield;                                          # в начале установим длину
    $f = fopen($file, 'r');
    while (!feof($f)) {                                        # проверка на конец файла
        $length = yield fread($f, $length);       # выбрасываем блок данных
    }
    yield false;                                                    
}
function processBytesInBatch(Generator $byteGenerator) {              
    $buffer = '';
    $bytesNeeded = 1000;
    while ($buffer .= $byteGenerator->send($bytesNeeded)) {           # всегда считываем порцию разного размера
       // проверяем, достаточно ли данных в буфере
        list($lengthOfRecord) = unpack('N', $buffer);
        if (strlen($buffer) < $lengthOfRecord) {
            $bytesNeeded = $lengthOfRecord - strlen($buffer);
            continue;
        }
        yield substr($buffer, 1, $lengthOfRecord);                                    
        $buffer = substr($buffer, 0, $lengthOfRecord + 1);
        $bytesNeeded = 1000 - strlen($buffer);
    }
}
$gen = processBytesInBatch(fetchBytesFromFile($file));
foreach ($gen as $record) {
    doSomethingWithRecord($record);
}
</code>

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

Нужно боольше примеров!

Вообще генераторы можно применять во многих задачах. Одна из них — симуляция потоков. Сначала мы определяем каждый поток как генератор. Затем выбрасываем сигнал управления родителю, чтобы тот смог передать сигнал для работы следующему потоку. Построим такую систему, которая работает с разными источниками данных (работаем с неблокирующим вводом-выводом). Вот пример такой системы:

<code class="php">function step1() {
    $f = fopen("file.txt", 'r');
    while ($line = fgets($f)) {
        processLine($line);
        yield true;
    }
}
function step2() {
    $f = fopen("file2.txt", 'r');
    while ($line = fgets($f)) {
        processLine($line);
        yield true;
    }
}
function step3() {
    $f = fsockopen("www.example.com", 80);
    stream_set_blocking($f, false);
    $headers = "GET / HTTP/1.1\r\n";
    $headers .= "Host: www.example.com\r\n";
    $headers .= "Connection: Close\r\n\r\n";
    fwrite($f, $headers);
    $body = '';
    while (!feof($f)) {
        $body .= fread($f, 8192);
        yield true;
    }
    processBody($body);
}

// 3 потока (step) имеют схожий функционал - выбрасывают true, тем самым давая сигнал, что он еще занят

function runner(array $steps) {                    
    while (true) {                                                # снова бесконечный цикл, в котором перебираем потоки
        foreach ($steps as $key => $step) {  
             $step->next();                                    # возобновляем работу потока с с момента последнего yield
             if (!$step->valid()) {                           # проверяем, завершился ли поток и завершаем (удаляем) его
                 unset($steps[$key]);
             }
        }
        if (empty($steps)) return;                      # если потоков нет - завершаем работу
    }
}
runner(array(step1(), step2(), step3()));
</code>

Заключение

Генераторы — ОЧЕНЬ мощная штука. Они позволяют очень сильно упростить код. Подумайте только, вы можете написать функцию для диапазона чисел в одну строчку кода:

<code class="php">function xrange($min, $max) {
    for ($i = $min; $i < $max; $i++) yield $i;
}
</code>

Коротко и просто. Легко читается, легко понять как работает и очень производительно — быстрее, чем с итератором.

Оригинал статьи — Anthony Ferrara @ blog.ircmaxell.com

Кратко о генераторах

— Не добавляют нового функционала в язык
— Быстрее*
— Возобновление работы генератора происходит с последнего «выброса» yield
— В генератор можно отправлять значения и исключения (через метод throw())
— Генераторы однонаправлены, т.е. нельзя вернуться назад
— Меньше кода в большинстве случаев, более простые для понимания конструкции

* Основываясь на этих результатах.
При больших масштабах перебора — генераторы быстрее. Примерно в 4 раза быстрее чем итераторы и на 40% быстрее обычного перебора. При небольшом количестве элементов могут быть медленнее обычного перебора, но все еще быстрее итераторов.

Если сообщество одобрит перевод и посчитает его хорошим (а главное, не утверждающим чепуху и не меняющим суть кода), мне будет интересно иногда переводить другие статьи.
Думаю, не будет лишним перевести и собрать в кучку статьи, публикуемые сейчас на phpmaster про структуры данных.
Также буду рад любым замечаниям, наставлениям, комментариям про ошибки как в тексте с кодом, так и в самом переводе.

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

UPD: Изменил расплывчатую формулировку, про которую говорили в комментариях.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Chaos Construction 2013: hackquest review-writeup

Как многие знают, на этих выходных в Санкт-Петербурге проходил фестиваль компьютерного творчества, в т.ч. на которым был hackquest (по типу Capture The Flag). Так как у меня сейчас нет личного блога, решил поделиться решением заданий здесь, думаю многим будет интересно :) в т.ч. есть были задачи, которые обсуждались на Хабре (заливка «запрещенной» музыки в ВК). Тематика была — Prism, АНБ и т.д.
Я не сохранил весь список заданий, но многие из них еще работают, восстанавливаю по памяти.

iPrism (mobile)

hack
this
secret
app
Скачиваем, находим приложение под iOS. Я не особо силен в реверсе, решил оставить на после. Но читая твиттер (полезно быть подписанным на организаторов), наткнулся на запись о сервисе hackapp.com
imageHackApp is web based service, for mobile apps static security analysis. It identifies critical and suspicious information in bundle, such as:
— Certificates and keys
— Authentication secrets
— License Control
— Compilation flaws
Сервис для поиска security багов в мобильных приложениях. Грузим наш файл, он генерит по нему отчет — hackapp.com/open#e55bece90691913812ef6e0da5c8278a, находим ключ
Affected files:
— b00067.app/Defaults.plist
Plain text authentication secrets seems to be saved in app bundle

AuthTokenString:C_C_13_F_L_@_G:8204e7efa933e2521a69417c4ab2357e

Flag: 8204e7efa933e2521a69417c4ab2357e

Prismtestm (web)

Скажу сразу, что это задание я не решил. Решение спросил после у команды (Hardc0de). Переходим на сайт задания, видим вебсайт с формой, где можно заполнить адрес проверки сайта на «PRISM» (обязательно попадающий под регулярку (.*).com ). Сразу заподозрил тут SSRF (1 причина — организаторы ONSec, вторая — просто логически). Копал SSRF Bible, зарегал домен .com, натравил скрипт на свой сервер с включенным tshark — ничего, в общем, как только не бился. Решение — обходим регулярку через /?, т.е. в хост пишем
127.0.0.1:80/?.com
Заставляем скрипт коннектится к локалхосту (?.com просто вырезается в функции на сервере как URI), передаем так же &debug (который можно было увидеть в комментах html). Момент в том, что порт надо указывать обязательно, иначе ничего не заводилось. А через параметр debug нужно провести SSRF, примеры можно найти в разделе Smuggling examples (SSRF bible). И копаем.

listen2me (stegano)

To bypass PRISM guys sometime uses this technique
Flag is MD5(message_from_MP3)
Задание не решил никто. Качаем файл, определяем, что это не mp3 (по заголовкам), даем расширение архива, открываем — архив битый, внутри два файла — calc.exe и reverse_something.txt. Начинаем копать, внутри находятся заголовки JPEG задом наперед. Вытаскиваем картинку, в картинке тоже стегано. Вроде как и в ней — ключ.

Gener (web)

NSA produced high secure PRNG source
По ссылке — исходник
<code class=""><?php
function reallySecureRandom(){
    $seed = (double)microtime()*1000000;

    $seed = $seed * (getmypid()>0?getmypid():1);
    $seed = $seed * (getmygid()>0?getmygid():1);
    $seed = $seed * (getmyinode()>0?getmyinode():1);
    $seed = $seed * (getmyuid()>0?getmyuid():1);
    $seed = $seed * (memory_get_usage()>0?memory_get_usage():1);

    mt_srand($seed);

    return mt_rand().mt_rand();
}
if($_COOKIE['token']===md5(reallySecureRandom())) echo file_get_contents('/tmp/flag.txt');
?></code>
Задача довольно ясная, нужно выставить себе куку по этому алгоритму. microtime — можем узнать через заголовок date, который отдает скрипт. pid/gid/uid — некоторые будут равны нулю, некоторые не такие большие, чтобы перебрать. memory_get_usage — запустить скрипт у себя, замерить расход памяти (при чем расход будет разный на x32 и x64). А вот с getmyinode было непонятно, так как значение действительно большое. В общем каким-то магическим образом задание решалось с $seed = 0. Т.е. код для генерации куки:
<code class="php"><?php
 mt_srand(0);
echo md5(mt_rand().mt_rand());</code>

Crackme (reverse)

NSA use this program to produce a secret key.

Flags is MD5(key)
.
Не решал, реверс под macos. Все, что попробовал — прогнать через strings :)

inveter

Reverse the 480120101078 with #chaosconstructions2013.
Hackmap around are Fibonacci numbers up to the 0x10.
Hint: 480132102026 and 481214218007 fit too.

Flag is MD5(result)
Задание не решил никто. Были разные мысли, какие правильно — не уверен, так что писать ничего не буду)

CryptoMsg (reverse)

#i#<L4w1u0q)mT9Q — ????????
1evryyone lies6 — 44,~yteU<<*sZOe
1234567 — )Wj~5Kb
1234568 — *Wj~5Kc
2345678 — 1Ym$:Qi
abcdef — FX=#hP
abcdef1 — YY>$iQb
hackers — ]_D1vj_
1337hackers — |\o(pS8%j^S
hackers1337 — UcH5znct)<S
task for cryptoanalysis — !{p]]E6**ma\ND5vfI72'pe
you will never break this cipher! — q:11*saOO?&|cWW;/tWDD:$mbbG2$lSGH

Flag is MD5(????????)

Download crypt3r: ./ccrypto.jar
Нужно расшифровать первое сообщение, имея тулзу. Качаем ccrypto.jar, распаковываем через java.decompiler.free.fr/, получаем исходник приложения. Криптофукция
<code class="java">void encrypt() {
    int val = 0;

    this.buff = new ArrayList();
    for (int i = 0; i < this.input.length(); i++)
    {
      val = this.input.charAt(i);
      val -= 32;
      if (i > 0)
      {
        val += ((Integer)this.buff.get(i - 1)).intValue();
      }
      else
      {
        val += this.input.length() + 13;
      }
      if (val > 94)
      {
        val -= 94;
      }
      Integer Val = Integer.valueOf(val);
      if (i == this.input.length() - 1)
      {
        int temp = 0;
        temp = ((Integer)this.buff.get(0)).intValue() + val;
        if (temp > 94)
        {
          temp -= 94;
        }
        this.buff.set(0, Integer.valueOf(temp));
      }
      this.buff.add(Val);
    }
    for (int i = 0; i < this.input.length(); i++)
      this.output += String.valueOf((char)(((Integer)this.buff.get(i)).intValue() + 32));
  }
}</code>

Я решал уже во второй день этот таск, а так как я не ложился спать и остался в клубе (ночью решал другой таск), то меня просто уже не хватило на этот алгоритм) помог друг, сосчитал вручную. Обратный алгоритм не так тривиален, как кажется, попробуйте :)

WPA / WPS (WiFi)

Объединил два задания, так как похожи, WPA
You have router at CC2013, which wants to be hacked.
Tricky admin have hidden ESSID of it's AP.
Use all your skills to penetrate in it's network

Flag is MD5(key)

WPS
There is a white box which broadcast wifi somewhere in the hack zone. You need to penetrate into it's network.
BTW some people say it supports WPS and first 4 digits of pin were saved ;) happy hacky

Flag is MD5(key)

Идем в хак-зону, грузимся с backtack и делаем все по гайдам. С WPA по стандартному словарю ключ находится за полсекунды.
Гайд по WPA — www.aircrack-ng.org/doku.php?id=cracking_wpa
На русском про WPS — habrahabr.ru/company/xakep/blog/143834/ (кстати, wps не сделал, не было времени. Там просто надо было ждать успешного брута).

onside

Таски прямо на месте. Подходим, спрашиваем, говорят — нужно найти камеры, около которых есть наклейки с надписями. Нужно прочитать, что на них, и сообщить организаторам, при этом не попав на них лицом. Варианты решения — разные) Сообщают, что камер < 5
И еще один был, trivia. 5 вопросов, среди которых есть один на который я убил очень много времени — «Назовите хакерскую атаку, название которой состоит только из hex символов». Всякие dd05 или fl00d не подходят, т.е. замена не сработает. Задание решено, у кого-нибудь есть идеи? :)

USBsticks

Get a USB stick from CC2013 to find a key
Подходим, лежит куча флешек. На одной из них был flag.txt, сдаем.

И два самых интересных таска, на мой взгляд.

androface (mobile)

Unlock Android device from CC2013 hack-zone
Подходим, дают планшет samsung с android 4.1, при тебе его лочат face-авторизацией под человека с конференции. Нужно разлочить, количество попыток — 5. Находим баг

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

VKmusic (reverse)

This task is top secret and came to you directly from Edward. Since he lives in Moscow now, he would like to feel the true spirit of Russia and listen to free music on VK.
However, his favorite song is currently banned. You need to find out the mechanism of detection and upload the song.
The initial analysis showed that it is enough to replace exactly three bytes to bypass «VKAF».
The answer to the task will be an MD5 hash of concatenated offsets in the file of those bytes.

Note: replace the lower two bytes with zeroes for each offset before hash calculation (i.e. 12345 --> 12300)
song
Эта тема уже поднималась на Хабре
Загрузка заблокированных аудиозаписей в «ВКонтакте» — habrahabr.ru/post/183554/
Блокировка аудиозаписей Вконтакте. Восстанавливаем плейлист — habrahabr.ru/post/183470/
В т.ч. там в комментах есть упоминание на выступление, где рассказывается про проверку загруженных записей. Посмотрев видео становится понятно, что проверяются конкретные универсальные байты (т.к. фаззинг с подменой байт в центре, в конце ничего не дал) для всех типов файлов. Организаторы написали, что нужно найти 3 байта и от них взять хэш — и будет ключ. Но в ночь с 10 на 11 было найдено решение всего в 1 байт, которое, к сожалению, не могу здесь опубликовать :) но дать направление — байт чисто визуальный, все данные файла сохраняются.
Качаем трек с задания (который не загружается в ВК), меняем 1 байт — вуаля, все работает.
Утром показал решение — дали флаг вручную :)

Было занято первое место и дали вот такую крутую штуку. Вроде все, спасибо организаторам, было круто :)


Награждение

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Теория цвета в цифрах

Разные люди могут по-разному представлять один и тот же цвет по его названию. Например голубой цвет может на самом деле быть цветом морской волны или небесным. Гораздо точнее цвет определяется шестнадцатеричным кодом, всего существует 16777216 комбинаций. Поэтому дизайнеру может быть полезно распознавать цвет, просто взглянув на его hex-код.

Основы

Начнем с простого: рассмотрим обычный hex-код, где каждая из трех пар цифр контролирует один из цветов RGB — красный, зеленый, синий. Числа могут принимать значения цифр от 0 до 9 и букв от A до F.



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



То есть величина чисел в парах означает количество цвета, проще говоря, если все числа максимальные, то в результате будет белый цвет — #FFFFFF, если числа минимальные, нули, то цвета нет, получается черный — #000000. Если изменять каждую пару, то получается: #FF0000 — самый яркий красный, #00FF00 — самый яркий зеленый и #0000FF — самый яркий синий. Соответственно, #00FFFF — самый яркий голубой, #FF00FF — самый яркий пурпурный и #FFFF00 — самый яркий желтый.



Распознавание цвета

Шестнадцатеричный код может быть сокращен с шести символов до трех. Например цвет #FAE означает #FFAAEE. Такая возможность иногда помогает упростить код, и что важнее, легко сократить количество оттенков, если это требуется.

В большинстве случаев распознать цвет по hex-коду можно, учитывая только первые цифры пар. В примере ниже понятно, что цвет смешан из большого количества красного, немного синего, а зеленого совсем нет.



Понимание цвета по hex-коду позволяет веб-дизайнеру быстрее ориентироваться в коде страницы, кроме того, можно всегда произвести впечатление на коллег или клиентов, сказав «Ах, какой прекрасный оттенок бордового».

Можно также легко менять яркость, оттенок или насыщенность цвета, отредактировав лишь его шестнадцатеричный код. В первом примере ниже одна из пар меняется с шагом в 10%, при этом растет яркость цвета. Во втором примере яркость растет, но насыщенность падает:



Подчеркивание ссылок

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

  • Для темного текста на светлом фоне делаем ссылки ярче.
  • Для яркого текста на темном фоне делаем ссылки темнее.
Чтобы это работало, необходимо использовать тег span внутри каждого тега a, например:

<code class="css">a { text-decoration:underline;color:#aaaaff; }
a span { text-decoration:none;color:#0000ff; }
</code>


Получившиеся ссылки легче читаются, т.к. подчеркивание не смешивается с символами. Однако добавлять span в каждую ссылку не очень рационально. Поэтому можно убрать подчеркивание ссылок, но при этом добавить border-bottom:

<code class="css">a { text-decoration: none; border-bottom: 1px solid #aaaaff; }
</code>

Цвета контента

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

<code class="css">h1, p { color: #797979; }
</code>


Уменьшение первых цифр в парах hex-кода повысит контрастность текста, а значит читабельность улучшится:

<code class="css">h1 { color: #797979; }
p { color: #393939; }
</code>


Редактирование фона

Легко управлять фоном, изменяя hex-код цвета:

  • #404040 — нейтральный
  • #504030 — теплее
  • #304050 — холоднее


Фон страницы визуально более чувствителен к изменениям цвета, чем контент. Поэтому можно легко сделать его теплее или холоднее, корректируя и вторую цифру в парах hex-кода. Например:

  • #404040 — нейтральный
  • #594039 — теплее
  • #394059 — холоднее


Подбор и комбинирование цветов

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



Использованный материал и полезное чтиво



Источник: habrahabr.ru,
получено с помощью rss-farm.ru


ZTE Open Firefox OS вскоре будет продаваться на eBay по 80 долларов



Сегодня объединенное заявление о скором выходе в свет нового смартфона с Firefox OS сделали Mozilla и ZTE. В анонсе было указано, что смартфон ZTE Open «вскоре» появится в продаже. К сожалению, уточнить точную дату выхода телефона нельзя, компании ее не сообщили. Зато известно, что девайс будет продаваться уже разлоченным, без привязки к операторам. Кроме того, покупатели смогут приобрести только телефон с корпусом оранжевого цвета, других альтернатив пока нет.

Цена, как и говорилось в заголовке, составит всего 80 долларов США, как для американских покупателей, так и для европейцев (во всяком случае, для англичан цена составит все те же 80 долларов). Функциональность устройства будет стандартной, и не стоит ожидать чего-то принципиально нового. Сообщения, электронная почта, звонки, возможность устанавливать новые приложения — это и все.

ZTE Open управляется процессором Qualcomm MSM7225A (1 ГГц). В оснащение аппарата также входят 256 Мб оперативной и 512 Мб встроенной памяти, 3,5-дюймовый сенсорный дисплей с разрешением 320 х 480 пикселей и аккумуляторная батарея емкостью 1200 мАч.

По словам разработчиков, ZTE Open разработан для тех пользователей, кто приобретает смартфон впервые. Сейчас компании работают над маркетинговой стратегией, которая, в идеале, позволит убедить достаточно большое количество покупателей в том, что смартфон им нужен. Само собой, доступность телефона на eBay открывает устройству дорогу и в страны, куда ZTE Open не будет поставляться официально.

К слову, в России поставками телефонов от ZTE будут заниматься «МегаФон» и «ВымпелКом». С этими компаниями заключен официальный договор.

Via cnet

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


ActionBar на Android 2.1+ с помощью SupportLibrary

Здравствуй, Хабрахабр!

Недавно я писал о том, что Google добавил поддержку ActionBar в свою Support Library. Думаю, стоит рассказать, как же им пользоваться. Под катом — инструкция по правильному импорту библиотеки в свой проект и основные моменты использования SupportActionBar.

Импорт библиотеки
Чтобы наш ActionBar был виден на старых устройствах, нужно наследовать тему приложения от Theme.AppCompat. Сама собой она ниоткуда не возьмётся, поэтому нужно создать проект библиотеки (оригинальная инструкция на английском для Eclipse и Android Studio здесь(смотреть пункт Adding libraries with resources)):
1. Сначала нужно убедиться, что у нас закачана последняя версия Support Library. Для этого открываем SDK Manager и листаем в самый низ, до папки Extras. В ней есть пункт Android Support Library – он то нам и нужен. Обновляем его до последней версии (сейчас – rev. 18), если не сделали этого раньше.
2. Обновили? Молодцы. Теперь нажимаем File > New > В папке Android выбираем Android Project from existing code.
3. Нажимаем кнопку Browse… и ищем нужную нам папку. Путь до неё примерно такой: <ваш SDK>/extras/android/support/v7/appcompat/. Выделяем появившийся пункт в списке и нажимаем Finish.
4. Теперь у вас в Project Explorer должен появиться проект android-support-v7-appcompat. Открываем его, в папке libs/ на обеих .jar – файлах кликаем правой кнопкой и нажимаем Build Path > Add to Build Path.
5. Щелчок правой кнопкой мыши по проекту, выбираем Build Path > Configure Build Path.
6. На странице Build Path во вкладке Order and Export отмечаем два только что добавленных .jar – файла и снимаем отметку с Android Dependencies.
7. Нажимаем ОК для сохранения изменений. Всё – библиотека готова к использованию!

Создание приложения
Теперь создадим проект своего приложения, которое мы и будем делать. Имя – SupportActionBarDemo, пакет – com.habrahabr.sabd, минимальный API level 7 (таковы требования библиотеки). Создаём Activity, имя – MainActivity, layout – main.
Теперь кликаем правой кнопкой мыши по этому проекту и нажимаем Properties. На странице Android под заголовком Library нажимаем Add и выбираем в появившемся окне android-support-v7-appcompat, затем – ОК и ещё раз ОК, чтобы сохранить изменения. Теперь библиотека добавлена в проект!

Простой пример
Прежде всего идём в res/values/styles.xml и пишем

<code class="xml"><style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light" > . . .
</code>

Теперь ActionBar будет виден на любых версиях андроида.

Открываем res/values/strings.xml и добавляем строки:

<code class="xml"><string name="action_item_1">Item 1</string>
<string name="action_item_2">Item 2</string>
<string name="action_item_3">Item 3</string>
</code>

Открываем res/menus/main.xml и пишем там:

<code class="xml"><menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:sabd="http://schemas.android.com/apk/res-auto" >
    <item
        android:id="@+id/action_settings"
        android:title="@string/action_settings"
        android:icon="@android:drawable/ic_menu_add"
        sabd:showAsAction="always" />
    <item
        android:id="@+id/action_item_1"
        android:title="@string/action_item_1"
        android:icon="@android:drawable/ic_menu_delete"
        sabd:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_item_2"
        android:title="@string/action_item_2"
        android:icon="@android:drawable/ic_menu_add"
        sabd:showAsAction="ifRoom|withText" />
    <item
        android:id="@+id/action_item_3"
        android:title="@string/action_item_3"
        android:icon="@android:drawable/ic_menu_add"
        sabd:showAsAction="never" />
</menu> 
</code>

Обратите внимание на атрибуты xmlns:sabd=«schemas.android.com/apk/res-auto» и sabd:showAsAction – без них ActionBar будет неправильно работать. Иконки случайные, значения не имеют. Я всё-таки напишу, что означает атрибут sabd:showAsAction:

always — элемент всегда будет виден, если места не хватает, заголовок будет показан не полностью
ifRoom — элемент будет виден, только если для него есть место
never — элемент никогда не будет виден, для его показа нужно нажать кнопку Меню на устройстве или кнопку Overflow на ActionBar при отсутствии первой

withText -элемент будет показываться только с его заголовком
collapseActionView — элемент может сворачиваться в кнопку или разворачиваться на всю ширину Actionbar по нажатию, далее я приведу его пример

Теперь приступаем непосредственно к написанию кода. Первым делом в коде Activity нужно заменить extends Activity на extends ActionBarActivity и добавить её в импорт. В последних версиях ADT при создании Activity автоматически создаётся метод onCreateOptionsMenu(Menu menu), в котором мы и создаём меню:

<code class="java">import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;

public class MainActivity extends ActionBarActivity {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Log.d("MENU", "Cliced MenuItem is " + item.getTitle());
		return super.onOptionsItemSelected(item);
	}
}
</code>

Запускаем приложение и видим наш ActionBar:



Item 2 не отобразился, так как для него не хватило места. Item 3 ни при каких условиях не будет виден, потому что мы выставили атрибут sabd:showAsAction=«never». Добраться до них можно с помощью кнопки «Меню» на устройстве.
Обрабатывать нажатия на элементы меню можно там же, где и раньше — в методе onOptionsItemSelected(MenuItem item). Обрабатывать нажатия на иконку приложения можно в этом же методе, она имеет ID android.R.id.home. Чтобы добавить на ActionBar кнопку «Вверх» («Up Button»), нужно использовать метод ActionBar.setDisplayHomeAsUpEnabled(boolean showHomeAsUp):

image

Поиск

Иногда нужно сделать поиск, например, как в Google Play. На помощь приходит ActionView. Открываем res/menu/main.xml и удаляем 3 последних элемента — они нам не нужны, а место занимать будут. Вместо них добавляем один новый:

<code class="xml"><item android:id="@+id/action_search"
    	android:title="@string/action_search"
        android:icon="@android:drawable/ic_menu_search"
        sabd:showAsAction="always|collapseActionView"
        sabd:actionViewClass="android.support.v7.widget.SearchView" />
</code>

атрибут sabd:actionViewClass=«android.support.v7.widget.SearchView» обозначает, какой View будет использован вместо обычного. Текст collapseActionView в атрибуте sabd:showAsAction говорит о том, что ActionView может быть сворачиваться в кнопку или разворачиваться на всю ширину по нажатию. Чтобы использовать его в Activity, изменим код MainActivity:

<code class="java">import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.SearchView.OnQueryTextListener;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends ActionBarActivity implements OnQueryTextListener {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		
		MenuItem searchItem = menu.findItem(R.id.action_search);
	    SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
	    searchView.setQueryHint("Поиск");
	    searchView.setOnQueryTextListener(this);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Log.d("MENU", "Cliced MenuItem is " + item.getTitle());
		return super.onOptionsItemSelected(item);
	}

	public boolean onQueryTextChange(String text_new) {
		Log.d("QUERY", "New text is " + text_new);
		return true;
	}

	public boolean onQueryTextSubmit(String text) {
		Log.d("QUERY", "Search text is " + text);
		return true;
	}
}
</code>

Запускаем приложение и видим:

image

Нажимаем на кнопку поиска:



Кстати, клавиатура появляется автоматически. Выйти из режима поиска можно, нажав на кнопку Вверх в левой части ActionBar или нажав на аппаратную кнопку назад.
В методе onQueryTextChange() мы получаем текст из поля ввода, когда пользователь набирает очередную букву. В методе onQueryTextSubmit(String text) нам даётся текст, который пользователь ищет. У SearchView есть такие полезные методы:
setQuery(CharSequence query, boolean submit) — изменяет текст в поле ввода на тот, который ему передают, опционально делает его конечным (начинает поиск)
getQuery() — возвращает текст, который сейчас есть в поле ввода
setQueryHint(CharSequence hint) — изменяет подсказку на ту, которую ему передают
getQueryHint() — возвращает подсказку
setSuggestionsAdapter(CursorAdapter adapter) — добавляет выпадающий список, как у AutoCompleteTextView
getSuggestionsAdapter() — возвращает адаптер этого списка
setOnCloseListener(SearchView.OnCloseListener listener) — ставит на него обработчик закрытия
setOnSuggestionListener(SearchView.OnSuggestionListener listener) — ставит на него обработчик нажатия на элемент выпадающего списка

Заключение
А ребята из гугла молодцы, не забывают о поддержке старых версий своей ОС. Например, фрагменты, ViewPager и NavigationDrawer с API v4 доступны, Actionbar – с API v7. Хотя мне кажется, что всё это было сделано ради Android 2.3, а более ранние платформы – так, «за компанию».

Буду рад, если эта статья кому-нибудь поможет :-)


А какие версии Android поддерживаете вы?


Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста. Проголосовало 219 человек. Воздержалось 78 человек. Источник: habrahabr.ru,
получено с помощью rss-farm.ru




Android 1.5+



Android 1.6+



Android 2.1+



Android 2.2+



Android 2.3+



Android 3.0+



Android 3.1+



Android 3.2+



Android 4.0+



Android 4.1+



Android 4.2+



Android 4.3+

Привилегия на счетный снаряд, выданный учителю музыки Куммеру 29 марта 1847 г. на 10 лет

image

Продолжаю публикацию русских привилегий на вычислительные машины. Второй из патентов, известных мне (и не только мне — устройство пользовалось большой популярностью, применялось добрую сотню лет). Источник: «Журнал мануфактур и торговли», 1847 г., № 4-5.

image
image
image
image
image
image
image
image

image

P.S. Так выглядели счетные снаряды Куммера, производившиеся в Европе спустя более чем полвека, уже под другими наименованиями.

image

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Между Samsung Galaxy S III и OPPO Find 5 (довольно-таки подробно о последнем)

Выбирая новый гаджет, мы, логично, хотим, чтобы он был лучше и интереснее старого. Для кого-то важно, чтобы девайс соответствовал тенеденциям, кому-то обязательно наличие большого количества ядер и более мощной графической составляющей, кто-то уповает на камеру, в том числе и я. И все мы находимся в поиске Того Самого! Я его почти нашла – им оказался OPPO Find 5, однако, кое в чем мой Samsung Galaxy S III оказался лучше, поэтому я повременила с покупкой. И все же Find 5 покорил меня. Хотите знать чем?



Критерии выбора или как выбирают девочки

Я отношусь к той немногочисленной категории людей, которые не гонятся не скупают все новинки на мобильном рынке. Мне важно другое – чтобы гаджет отвечал всем моим запросам, а именно:
1) Был симпатичным (я ж девушка =))
2) Служил мне верой и правдой как можно дольше
3) Был шустрым
4) Имел большой экран (лично я не представляю, как может быть удобно набирать текст на экране 4.3 дюйма)
5) Громкий динамик (очень актуально в шумном городе, особенно в Москве)
6) Занятный интерфейс (фишечки аппарата, куча настроек, интерактивная оболочка)
7) Самое главное – камера! (неоднократно говорила в обзорах о том, что люблю фотографировать все вокруг, тем более, что иногда проще взять с собой смартфон, чем огромную бандуру под пол кило и более)

И вот мой Samsung Galaxy S III идеально подходит под все критерии. Однако все мы знаем, что современные смартфоны долго не живут (нет, если вы только звоните по аппарату или он выпущен в каком-то далеком 2008 году, то, уверена, он у вас живее всех живых!) И от новой покупки никуда не деться. Вот и я спустя год начала задумываться о том, что было бы здорово (хотя и не обязательно) приобрести новый смартфон, но так как особой надобности в этом нет, то эти мысли так и оставались мыслями, пока я не познакомилась с брендом OPPO и его флагманским Find 5. Тем более, производитель уверяет, что аппарат ничем не хуже современных флагманов SGS4, HTC One и Sony Xperia Z. А почему OPPO, а не Samsung, HTC или Sony? А, может быть, и Nokia? И сейчас будет типично женский ответ – потому! Ответ такой: о SGS3 множество не очень лестных отзывов от журналистов, отлично разбирающихся в гаджетах; HTС мне никогда не нравились и все тут; Nokia – закрытая ОС (собственно, как и iPhone), а Sony Xperia Z – делает не очень качественные карточки, да и дизайн у него грубоватый, как-то не зацепил. А у OPPO внешность вроде бы не банальная, не глянцевый пластик, а матовый софт-тач, есть белый цвет и вообще он красивый! А еще у него есть экран разблокировки с милым котейкой (но об этом ниже).

Поэтому OPPO. Захотелось мне его! Но прежде чем бежать в магазин, поддавшись эмоциям, решила воспользоваться привилегией обзорщика и взять вожделенный аппарат на тест, чтобы взвесить все «ЗА» и «ПРОТИВ». Да, скажете, чего взвешивать – пошел и купил, раз хочется и нравится. Но мне с этим аппаратом ходить долгое время! И я не хочу покупать гаджет, который мне потом надоест спустя 2 месяца. В общем, как-то мне привили, что ко всему надо подходить с умом и не размениваться по мелочам. Ох, не в ту степь занесло, давайте-ка уже о смартфоне….

Внешний вид и комплектация

Коробка у OPPO Find 5 выполнена в черном цвете. Крышка на магните. Внутри мы видим ванночку для смартфона, а под ней стандартная комплектация — наушники, кабель microUSB, блок зарядного устройства, ключ для выемки слота под micro-SIM и документация.



Как я уже говорила, внешне OPPO Find 5 мне нравится.
Он имеет монолитный корпус, приятный на ощупь. Всю переднюю сторону занимает экран (Gorilla Glass 2 ) с небольшой белой пластиковой полоской внизу.

Задняя сторона оснащена 13 Мп камерой, двойной вспышкой, микрофоном (для шумоподавления), динамиком и надписью OPPO.


Если сравнивать с SGS3, то выглядит он, конечно, более стильно (ох, и не люблю я это слово, но оно сюда оч хорошо подходит!). По размерам они почти идентичны, но Samsung кажется толще.



Края у Find 5 заостренные, у SGS3 – закругленные.


Смотреть в выключенный экран, как в зеркало, можно на обоих смартфонах :) Ой, не говорите, что никогда так не делали – не смотрелись в смарт как в зеркало?


Сверху лицевой панели находится 2Мп камера, датчики приближенности и освещенности.


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


На правом «боку» расположились клавиши регулировки громкости. Нащупываются легко.

На левом – клавиша включения и отсек micro-SIM

Вот странное расположение клавиш, обычно же кнопка включения справа, а клавиши регулировки громкости слева.

На нижнем торце — порт microUSB и микрофон, на верхнем – вход для наушников 3.5 мм


Экран

Сейчас экраном Full HD не удивить искушенного гаджетомана, однако все же не многие смартфоны могут похвастаться разрешением 1920 на 1080 точек. Разве что флагманы. А ведь совсем недавно (в ноябре 2012) был представлен первый в России смартфон с Full HD экраном – Sharp Aquos Phone 930, помните такой? У него еще не было нормальной оптимизации, да и мало игр было адаптировано под Full HD. Сейчас же смартфоны с высоким разрешением мало того, что работают шустро, так еще и могут день проработать от одной батареи! Во, до чего дошел прогресс! =)

Мне экран нравится – сочный, яркий, и не такой кислотный (вот никогда не замечала до этого, если честно), как у моего SGS3 – разница чувствуется уже после трех дней пользования Find 5.
Да даже если их положить рядом и поставить одну картинку на экран, то разница чувствуется. Но вот определить, что больше мне нравится AMOLED или IPS, стопроцентно не могу


Углы обзора хорошие. Яркости только вот хотелось бы побольше. И возможности регулировки яркости из быстрой панели настроек.

Горилла (которая Glass) защищает дисплей от царапин и нападения ключей, расчесок, ножниц и других монстров дамской сумочки. Но, думаю, со временем оборона чуть-чуть да будет пробита. Сужу по своему SGS3, у которого горилла «постарше», но которая чуть сдала оборону уже спустя месяц пользования.

10 касаний, вуаля!


Оболочка

Одной из фишек OPPO Find 5 я смело могу назвать его оригинальную оболочку – это не голый Android, а очень красивая, я бы даже сказала «интерактивная» обложка. Обзор данной оболочки вы легко можете найти в интернете, например, вот здесь keddr.com/2013/08/color-rom-luchshaya-storona-oppo-find-5/ Но я бы хотела остановиться именно на том, что зацепило меня и что, мне кажется, будет интересно пользователям.

Множество тем оформления.
Ой, ну это у любого андроида есть, скажет скептик. У любого, согласна. Да вот только я ни разу за год не задумалась обновить тему оформления своего телефона. Хотя нет, вру, задумалась, пошла в Play Market, ввела «Тема оформления» и зависла – ну как-то не очень, если честно. Ни о чем. Возможно, я плохо ищу? Но вот вся и фишка, что надо искать, что-то как-то правильно писать, где-то об этом читать… А в Find 5 все просто – есть специальный ярлычок, нажимаем на него и, вуаля, три раздела – обои, темы и экран блокировки.


Все наглядно, со скринами. Все красивое и яркое. Ну прям душа радуется. Собственно, что я сделала, как получила на тест Find 5? Правильно, установила себе новую тему оформления и экран блокировки с милым котэ =)
Ярлыки, кстати, в зависимости от темы, также меняются. Прям и не узнать некоторые!




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




Всплывающие смс-сообщения
Возможно (да я почти уверенна) эта функция часто встречается в смартфонах, но вот для меня это было откровением. Сидишь ты, допустим, в твиттере, тебе приходит сообщение и оно отображается в небольшом окошке прямо посередине экрана, при этом приложение, в котором ты сидишь, не уходит в фон и не закрывается. И ты можешь прочитать сообщение целиком и даже ответить на него. Либо же просто закрыть это окошко и продолжать дальше заниматься тем, чем занимался до этого – читать твиттер или смотреть фильм.

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

В остальном менюшка сообщений стандартная, только выглядит, конечно, покрасивше.


Жесты
Не многие смартфоны могут похвастаться данными «жестовыми» функциями.


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

Не сказать, чтобы нужно, но, мне кажется, забавно.

Обратная связь прямо в телефоне
В OPPO Find 5 есть встроенное приложение «Обратная связь», которое позволяет через Интернет отправлять вопросы сразу специалисту технической службы поддержки. И не надо звонить.


Возможность сохранить данные в «облако»
Создается учетная запись, которая позволяет сохранять ваши данные -фотографии, музыку, текстовые документы и т.д — в сетевое хранилище.

Стандартные приложения

Предустановленных приложений не много – и почти все от Google, но есть также Facebook, Kingsoft Office, NearMeCloud (приложение, позволяющее данные с телефона закидывать в «облако» и там их хранить). В остальном все стандартно, хоть и красиво нарисовано. Поэтому просто прилагаю скриншоты.






Настройки довольно обширные, делятся на три раздела «Общие», «Аудио» и «Экран».



В шторке уведомлений отображается, кстати, информация о том, сколько трафика вы накачали. В SGS3 такого нет, да и в других смартфонах на Android я этого еще не встречала. Кстати, строку быстрых настроек можно также настраивать.


Видеоплеер проигрывает без проблем файлы размером более 2 Гб. По крайней мере, Иллюзию обмана в HD-качества я смотрела без проблем. Но я не особый сторонник просмотра фильмов на столь маленьких диагоналях. Если смотреть фильм, то на большом экране, а лучше – в кинотеатре. Но это мое мнение.

Производительность

Работает OPPO Find 5 под управлением 4-ядерного процессора Qualcomm Snapdragon S4 с частотой 1.5 ГГц, за графику отвечает Adreno 320, оперативной памяти – 2Гб. Все это должно обеспечивать плавность и стабильность работы устройства. В принципе, так оно и есть. Не было никаких подлагиваний или зависаний. В общем, простому обывателю этот аппарат покажется шустрым и быстрым :) А вот для тех, кто любит цифры, прилагаю результаты тестов:
Antutu – 20 974
Quadrant – 7570
Vellamo – 1 743


Насчет игр. Я не геймер, поэтому мощная машинка, поддерживающая 3D-игры мне как-то особо не нужна. Максимум, во что играю – это Subway Surfers. Она на OPPO Find 5 идет на ура =)

Батеря

Здесь стоит аккумулятор на 2500 мАч. Наученная горьким опытом общения со смартфоном с Full HD экраном (Sharp 930), который разряжался спустя 5 часов интенсивной работы, я немного скептически отнеслась к аккумулятору, который больше аккума моего SGS3 на 400мАч…

Итак, что имеем: задрота социальных сетей (то есть меня), постоянно проверяющего Twitter, VK, Facebook, делающего фотографии для Instagram, проверяющего почту и разговаривающего по телефону около часа в день. Интернет всегда работает. Плюс пара-тройка смс.
С зарядки сняла утром (часов в 10) и в час ночи аппаратец пискнул и отрубился от потери последней капли энергии. Но тут следует учитывать, что пол дня я работала и телефоном практически не пользовалась (работал Wi-Fi и было несколько входящих звонков)
Графика расхода заряда батареи тут, кстати нет. Но можно посмотреть, на что расходуется батарея

То есть при моей стандартной нагрузке на смартфон, он проживет чуть меньше суток. В принципе, Samsung Galaxy S III живет столько же, хотя тут можно списать и на уже поднатаскавшийся аккумулятор.

В целом, меня порадовала автономность работы. Конечно, хочется, чтобы смартфон работал без подзаряки как можно больше, и, надеюсь, в скором времени появятся такие аппараты, причем не толстые, как например, Highscreen Boost, а вполне себе тоненькие и легкие.

Звучание

Телефон должен быть громкий! Иначе — зачем вообще телефон?:)

Динамик у Find 5, как и у большинства телефонов, расположен на задней стороне аппарата. Когда кладешь телефон на стол, звук немного приглушается.

Не скажу, что я такой супер ценитель качественной музыки, в общем, не разбираюсь я в том, качественно ли звучит музыка из динамиков или нет. Ну, звучит. Ну, мне нравится. Никаких шипений, хрипоты динамиков не замечала. Значит, все гуд? Динамик, кстати, громкий (хотя это не Nokia N95, которую в соседней квартире услышишь). Через наушники (естественно, сторонние) подача звука идет хорошо. Есть даже спец.настройка – «Вопсроизведение звука через динамик» и «Воспроизведение звука через наушники».




Для аудиофилов есть настройки «Dolby Effect» и «Dirac Effect». Я не отношусь к данной категории людей, поэтому сказать ничего не могу.

Камера

И вот он, камень преткновения! Вот все мне нравится в OPPO Find 5 кроме камеры.
Нет, она не ужасна, а вполне даже ничего так, но хуже, чем у SGS3. Кадры получаются слегка размазанными, при слабом хорошем освещении слегка «шумят». Совсем слегка. Кто-то скажет, что придираюсь, возможно, так оно и есть. Но вот мне не нравится, как OPPO фоткает по сравнению с Samsung и все тут! Единственное, макросъемка, признаюсь, у него на высоте!

Настроек камеры, кстати, не очень много. Я бы сказала даже мало. Надо устанавливать что-то сторонее. Из базовых мне понравился эффект «Красивое лицо» — все прыщи, неровности и даже веснушки убирает :D Однако при детальном и близком рассмотрении заметен так называемый «тональный слой», который и перекрывает все изъяны.
Настройка основной камеры:


Настройка фронтальной камеры:


Примеры фото (осторожно, большие фотографии!):


Эффект «Красивое лицо» сначала хотела продемонстрировать на себе, но тут вот с подругой встречалась, у которой много-много веснушек. Так вот данный эффект и веснушки даже убирает! Правда, лицо кажется каким-то немного неестественным.
Примеры фото:До
После

А вот у кого-то получается делать довольно-таки неплохие фоточки:


Другие особенности

Что бы еще хотелось бы рассказать об аппарате?
У него нет слота для microSD-карт. А это значит, что память вы расширить не сможете. Поэтому сразу надо покупать аппаратец с 32 Гб внутренней памяти.

При длительной нагрузке, обычно при играх, OPPO Find 5 греется. Не сильно, конечно, но греется. Мне, в принципе, все равно. Зимой даже хорошо – можно нос замерзший отогревать. Кстати, от подключения к компу он тоже греется.

При подключении смартфона к компьютеру, вы увидите уведомление, предлагающее выбрать один из трех режимов «Только зарядка», «Накопитель» (тогда ваш телефон будет виден на компе как съемный дикс) и «Режим мультимедиа». Не знаю, нужна ли функция «Только зарядка»? Как вы считаете? Мне кажется, это уже лишнее.


Сразу из Галереи можно перейти в режим фотографирования – внизу есть соответствующая строка. Мелочь, а приятно.


Для OPPO Find 5 периодически выходят новые прошивки, которые разрабатываются совместно с пользователями. Так, последняя версия (правда, еще бета-версия) прошивки называется Color ROM видоизменяет внешний облик телефона. Собственно, именно в этой оболочке содержится основная куча фишек, которые я описывала выше. Прошивку можно скачать на официальном сайте OPPO. Устанавливать не сложно. Я справилась.


Свайпа априори нет. Тем, кто переходит с Samsung-а, будет сложновато привыкнуть. Либо искать и устанавливать свайп (мне эта процедура не далась).

Ах, сюда вставляется micro-SIM. И вставляется она хитрым образом — с помощью специального ключика вытаскивается ванночка для сим-ки. Если потеряете ключик, то подойдет обычная скрепка, имхо.

Почти герой, но не мой

OPPO Find 5 – первый смартфон после, собственно, Samsung Galaxy S III, который я захотела себе приобрести. У него почти все идеально – дизайн, оболочка, автономность, быстрота работы. Но есть одно, с чем смириться не могу, ну никак – камера. Ну вот что-то меня отпугивает в ней. Возможно, дело тут в той же цветопередаче экрана, возможно, мой внутренний голос говорит мне: «Подожди чуть-чуть, скоро выйдет смартфон твоей мечты с отличнейшей оптикой!». Не знаю. Но пока что я решила отложить покупку. Тем более что особой нужды в нем нет. А вот если бы была, то тогда, может быть, я не кочевряжилась и купила бы его? А, возможно, дело в цене? Стоит ведь OPPO Find 5 на 16 Гб – 19 990 руб/605$ (на 32 Гб – 21 990 руб/666$). По характеристикам он, в принципе приближен к флагманам HTC One, Samsung Galaxy S IV и Sony Xperia Z, которые стоят на 5-6 тыс дороже. Но все же, компания, которая практически не известна на рынке, могла бы сделать цену еще меньше. Хотя, если посмотреть на их цены в Китае, разница между нашими и «ихними» ценами невелика…

В общем, буду ждать у моря погоды когда у OPPO выйдет новый смартфон с более качественной камерой (а поговаривают, так будет реально какая-то крутая камера) или же когда на меня что-то нападет, да пойду и куплю этот Find 5. А пока сижу с Samsung Galaxy S III и вроде не плохо :)

Подытожим:

Плюсы:
дизайн
оригинальная оболочка (не голый Android, юпи!)
Full HD экран
громкий динамик

Минусы:
камера
отсутствие слота для карты памяти
узкие бортики вокруг экрана и слишком близкое расположение клавиш к экрану из-за чего происходят часто лишние нажатия

P.S. Если что-то забыла упомянуть — пишите в комментариях, аппарат пока на руках, так что могу дополнить обзор :) Хотя, мне кажется, и так многобуков :)

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Crossfilter.js, dc.js и D3.js для визуализации Данных

Приветствую ценителей красивой и функциональной визуализации данных! Предлагаю вашему вниманию небольшой обзор нескольких JavaScript библиотек, которые вкупе с D3.js позволят создать интерактивную визуализацию многомерных данных с возможностью применения фильтрации «на лету».


Заинтересовались, тогда добро пожаловать под кат.

Примечание: Данная статья является в некоторой степени компиляцией нескольких статей из замечательного блога www.d3noob.org, переработанных и дополненных в соответствии с моим видением задачи визуализации данных.
Источник вдохновения:

Визуализация данных и аналитика

У нас в стране инфографика в основном ассоциируется с картинками, созданными дизайнерами (иногда весьма недурно), хотя последнее время стало активнее развиваться ещё и видео. Это лишь вершина айсберга, которую оккупировали маркетологи, истинная же мощь доступна лишь водолазам аналитикам-программистам. Но о сложившейся ситуации как-нибудь в другой раз, а сейчас давайте вернёмся к интерактивной инфографике. Обычно под словом «интерактивная» подразумевается возможность отображать тултипы, менять масштаб, иногда применять фильтры и менять структуру данных, но всё это, как правило, подчиняется заранее продуманной логике (сценарию). А теперь представьте, что вы можете управлять потоком данных сами, с минимальными ограничениями, представьте, что вы можете задавать произвольные простые (без формул) фильтры, не ограничиваясь выбором из списка. А теперь представьте ещё больше, а именно: все изменения практически мгновенно отображаются на всех графиках, представляющих многомерный массив данных. Звучит неплохо, не так ли?

Crossfilter.js

Crossfilter это JavaScript библиотека для работы с многомерными данными в браузере. Crossfilter обеспечивает экстремально быстрое взаимоизменение (менее 30мс) связанных между собой представлений данных (срезов многомерных данных) даже если входные данные содержат более миллиона строк. Библиотека создана людьми, имеющими непосредственное отношение к d3.js, это Mike Bostock и Jason Davies.

В основе работы с данными лежат принципы модного нынче Map-Reduce. Для человека, который с этим прежде не сталкивался всё это звучит довольно сложно и запутанно, так что давайте разбираться. Итак что обычно делают с многомерными данными (вспоминаем сводные таблицы из Excel)? Их обычно группируют всевозможными способами, суммируют, сортируют, подсчитывают частоту вхождения значений и т. д. За это и отвечает Reduce, а Map обеспечивает параллельное вычисление всех этих манипуляций. Конечно в реальности всё немного сложней, но, думаю, для первого приближения сойдёт.

Так что же может crossfilter

Как говорится, лучше один раз увидеть, а сделать это можно на Github странице библиотеки.


Перед нами информация о
231,083
полётах в различных разрезах. Здесь мы видим пять представлений данных: четыре столбчатых диаграммы и одна таблица. На графике
Time of Day
отображено распределение полётов в зависимости от часа.
Arrival delay
показывает распределение количества задержек рейсов, сгруппированных в 10-ти минутные интервалы.
Distance
показывает распределение рейсов по дальности полёта (интервал 50 миль).
Date
— количество рейсов в день. И всё это было отрендерено на стороне клиента, то есть у нас в браузере, согласитесь, неплохо для такого количества данных.

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

И самое главное, всё это великолепие «Released under the Apache License 2.0».

DC.js спешит на помощь

Если вы посмотрите код демо-примера для crossfilter, вы увидите, что он занимает более 500 строк. Всё потому, что crossfilter создавался не для визуализации данных, а для манипуляции ими. D3.js же, в свою очередь, создавался как раз для визуализации данных. Тут нам на выручку приходит библиотека dc.js за авторством Nick Qi Zhu, которая связывает две интересующие нас технологии в один мощный инструмент. К сожалению, все многообразие графиков D3.js нам доступно не будет, но тех что реализованы в dc.js достаточно для большинства случаев. DC.js поддерживает следующие типы графиков:

  • Bar Chart
  • Pie Chart
  • Row Chart
  • Line Chart
  • Bubble Chart
  • Geo Choropleth Chart
  • Data Table
Примеры реализованных графиков можно посмотреть на Github странице проекта. Библиотека тоже опубликована под лицензией«Apache License 2.0».

Больше инфографики красивой и функциональной

Ну вот, теперь вы знаете ещё несколько инструментов визуализации данных и можете создавать многокомпонентные графики с фильтрацией «на лету». Успехов вам в реализации ваших замыслов.

Хаб, посвящённый визуализации данных

Дорогие хабровчане, как вы смотрите на создание хаба Data visualization или Визуализация данных? Потому что сейчас из близких тематических хабов существует только хаб Инфографика, но он посвящён собственно инфографике (результатам), а не процессу её создания. Определения этих двух терминов можно найти в википедии: Infographic, Data visualization.
Так что всех заинтересованных прошу выразить своё мнение по данному вопросу.


Нужен ли новый Хаб, посвящённый визуализации данных?


Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста. Проголосовало 204 человека. Воздержалось 49 человек. Источник: habrahabr.ru,
получено с помощью rss-farm.ru




Нужен, отдаю предпочтение названию «Визуализация данных»



Нужен, отдаю предпочтение названию «Data visualization»



Не нужен, нечего засорять мой любимый хабрахабр сомнительными хабами!



Изложу свою позицию в комментариях

[RSS-пост] Обновленное видение подходов к ИБ от Gartner

Аналитики Gartner обновили документ двухлетней давности с обзором основных инициатив в области технологий и сервисов ИБ, которые необходимо реализовать для снижения рисков от внутренних и внешних угроз. Документ максимально высокоуровневый – одна иллюстрация плюс 2 страницы текста. Но на них поместились:
  • определение целей и задач обеспечения ИБ в современных условиях;
  • роль CIO в процессе обеспечения ИБ и пять факторов, которые он должен обязательно принимать во внимание;
  • описание структурированного 4-х этапного подхода к обеспечению ИБ.
Отличия от предыдущей версии документа минимальные – добавили блок для специалистов технического уровня с описанием 5 рекомендованных шагов для успешного обеспечения ИБ и заменили иллюстрацию.Новая картинка более симпатичная, хороша для презентаций руководству, но менее нагружена смыслом. Предыдущая была более технической и «говорящей», поэтому мне нравилась больше, хотя нарисована была простовато.

Впрочем, это не удивительно – ведь старая картинка была взята из значительно более объемного отчета «Research Roundup for Infrastructure Protection», в котором содержались развернутые рекомендации по выбору и внедрению упомянутых на картинке технологий ИБ. И очень отрадно, что центральным столпом защиты инфраструктуры аналитики Gartner определили технологии Endpoint Protection – ведь «Код Безопасности»  предлагает широкий набор продуктов для этих целей, а значит мы на острие прогресса JЯ всем рекомендую посмотреть этот документ, который может быть полезен для определения приоритетов и подготовки обоснования программ, направленных на развитие и адаптацию систем обеспечения информационной безопасности к изменяющимся условиям.

Степаненко Андрей, директор по маркетингу компании «Код Безопасности»

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[RSS-пост] Кто сторожит сторожей?

Компания iViZ Security, специализирующаяся на проведении тестов на проникновение, опубликовала свой очередной отчет «(In) Security in Security Products 2013», в котором отметила бурный всплеск числа уязвимостей в security-решениях. В 2012 году, на фоне примерно 20% роста общего числа уязвимостей, количество уязвимостей в security-продуктах выросло почти в 3 раза!И что самое прискорбное: по сравнению с общим объемом ошибок различного вида количество уязвимостей в security-продуктах, связанных с контролем доступа, управлением ресурсами и аутентификацией, несравнимо выше. При том, что подобные ошибки в security-продуктах, на мой взгляд, вообще не допустимы.
Что же рекомендуют делать в этих условиях эксперты компании iViZ Security?
Рецепт прост и сложен одновременно:
  • требовать от производителя не только сертификации продуктов, но и проведения тестирования на наличие уязвимостей;
  • проводить собственные тесты на проникновение для security-решений.
Могут ли заказчики выполнить эти рекомендации? Теоретически – да, но на практике получается, что выкручивать руки вендору и что-то от него требовать могут только мега-заказчики, а тратить дополнительные деньги на тестирование безопасности продуктов, предназначенных собственно для безопасности, никто не станет.Могут ли производители обеспечить более высокое качество своих продуктов? Конечно, могут. Есть целая область знаний, помогающая достичь этого результата и посвященная разработке безопасного (т.е. не содержащего ошибок и уязвимостей) программного обеспечения. Наиболее известными наработками в этой области являются:
  • Microsoft Security Development Lifecycle;
  • NIST Security Considerations in the System Development Life Cycle;
  • Cisco Security Development Lifecycle;
  • Software Assurance Maturity  Model и др.
Конечно, следование этим рекомендациям делает разработку более дорогой, но снижение числа ошибок и уязвимостей гарантированно приводит к уменьшению числа претензий от пользователей, что должно компенсировать затраты.В частности, «Код Безопасности» внедрил процесс разработки, основанный на комбинации жизненных циклов безопасной разработки Microsoft и Cisco. Все его этапы документированы в рамках сертифицированной системы менеджмента качества и включают, в том числе, расширенные методики тестирования, поиска уязвимостей и моделирование атак, что позволяет нам выпускать на рынок качественные и безопасные средства защиты информации.Кроме того, в связи с тем, что ФСТЭК России в своих последних документах по защите персональных данных рекомендовал применять программное обеспечение, разработанное с использованием методов защищенного программирования, мы планируем в скором времени разместить на сайте описание нашего процесса разработки.

Степаненко Андрей, директор по маркетингу компании «Код Безопасности»

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[RSS-пост] Анализируем новые приказы ФСТЭК России № 17 и № 21

О приказах ФСТЭК России № 17 и № 21 высказались, наверное, уже все эксперты сообщества, перемыли косточки и разложили по полочкам все новации нашего регулятора. Поэтому планируя вебинар на эту тему, мы рассчитывали на традиционное количество в 150–200 участников.

Реальность существенно превзошла наши ожидания. Более 600 зарегистрировавшихся участников – объективный показатель того, что информации по этой теме до сих пор не достаточно, наши партнеры и заказчики нуждаются в дополнительных разъяснениях новых положений.
Сама презентация не содержала каких-либо супероткровений; то же самое систематическое «раскладывание по полочкам» и наша позиция по некоторым спорным положениям. А вот сессия вопросов и ответов стала для меня настоящим испытанием, которое длилось дольше самой презентации. Мы получили более 50 вопросов самой разной направленности: от простого толкования тех или иных мер защиты до попытки разобраться в тонкостях лицензирования деятельности по защите информации.

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

1. Нужна ли оператору ПДн лицензия на ТЗКИ?
Информационное сообщение ФСТЭК России от 30 мая 2012 г. № 240/22/2222 «По вопросу необходимости получения лицензии ФСТЭК России на деятельность по технической защите конфиденциальной информации» допускает возможность работы без лицензии на ТЗКИ, если деятельность организации не направлена на получение прибыли от выполнения работ или оказания услуг по технической защите конфиденциальной информации.
Детали и иные условия, при которых эта возможность реализуется, подробно перечислены в сообщении, правда, с весьма неоднозначными формулировками. В соответствии с этой позицией ФСТЭК России лицензия на ТЗКИ для оператора ПДн не является обязательной, если деятельность по защите персональных данных является вспомогательной, выполняемой для собственных нужд.К сожалению, после запуска в январе 2013 г. нового сайта ФСТЭК России найти этот документ там не удалось, поэтому ищите его в информационно-правовых системах (например, http://www.garant.ru/products/ipo/prime/doc/70104166/).

2. Необходимо ли для существующих ИСПДн (для которых выполнены требования приказа № 58) выполнять требования по 21 приказу?
В соответствии с общими правилами нормативный акт применяется к отношениям, имевшим место после его вступления в силу и до утраты им силы. Поэтому действие приказа № 21 будет распространяться на вновь создаваемые системы защиты в информационных системах персональных данных.Отдельной ремарки заслуживает ситуация, когда ранее созданная система защиты ИСПДн модернизируется. В этом случае для легализации нового варианта системы защиты нужно следовать нормам нового приказа. Но глубина модернизации при этом ничем не регламентирована, поэтому каждый оператор, скорее всего, будет толковать эту ситуацию в свою пользу, откладывая переход на новые требования.Хотя провести классификацию существующей ИСПДн по новым критериям может быть полезно и не дожидаясь модернизации, потому что во многих случаях прежний класс К1 может превратиться в УЗ2, УЗ3 или даже УЗ4.

3. Есть ли понимание что такое «методы защищенного программирования» и как понять – какие продукты с использованием этих методов созданы?
Конечно, у всех компаний, занимающихся разработкой программного обеспечения, есть свое видение того, что понимается под «методами защищенного программирования», предназначенными для повышения уровня безопасности продуктов и снижения числа уязвимостей в них.

Одной из самых известных в индустрии моделей является жизненный цикл безопасной разработки Microsoft, базирующийся на нескольких ключевых принципах: безопасность при разработке, безопасность при использовании параметров по умолчанию, безопасность при развертывании и безопасность при обмене данными. Так, «Код Безопасности» осуществляет все свои разработки в соответствии с этой моделью.

Другим интересным документов на эту тему является NIST Special Publication 800-64 Security Considerations in the System Development Life Cycle, который охватывает не только программирование, а значительно более широкую область. NIST предлагает пятиэтапную модель, позволяющую обеспечить выполнение требований по безопасности в информационных системах, которые строятся из уже готовых и разрабатываемых по требованию заказчика продуктов.
Какого-либо списка продуктов, созданных в соответствии с методами защищенного программирования, не существует. Можно ориентироваться на декларации разработчиков, хотя следование этим методам не означает полного отсутствия ошибок или уязвимостей в их продуктах. Но их гарантированно будет существенно меньше, чем у разработчиков, такими методами не пользующихся.

Степаненко Андрей, директор по маркетингу компании «Код Безопасности»

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


#FailOverConf Украина состоится 3 октября в Киеве!

Шановні пані та панове! Рады сообщить вам, что специализированная технологическая конференция «FailOver Conference Украина» состоится 3 октября 2013 года в Киеве!

В начале апреля этого года мы провели первую «FailOver Conference» в Москве. Опыт ее проведения оказался очень удачным — в офф-лайне и он-лайне присутствовали около 800 участников (материалы прошедшей конференции выложены на Хабре).

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

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

В итоге, именно такую специализированную технологическую конференцию мы и анонсируем сегодня!

Уже сейчас в программе мероприятия подтверждены доклады Андрея Аксёнова (Sphinx), Максима Ищенко (dou.ua, Джинн), Сергея Аверина (Badoo), Сергея Рыжикова («1С-Битрикс») и других экспертов в области разработки отказоустойчивых проектов.

Практическую пользу посещения «FailOver Conference» разработчиками и системными администраторами сложно переоценить. Из отзывов о московском мероприятии:

Шел на конференцию с конкретной задачей: предложить заказчику схему инфраструктуры высоконагруженного веб-сайта. К концу конференции 3 варианта схемы были уже на планшете. Задача выполнена полностью. Спасибо!
Участие в конференции платное, однако до 20 августа действует минимальная символическая цена входного билета на мероприятие — 200 грн., так что следует поторопиться, чтобы успеть попасть в число первых участников «FaiOver Conference Украина».

Пожалуйста, регистрируйтесь и примите участие в конференции!

До встречи в октябре!

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Хватит писать регулярные выражения. Используйте вербальные выражения

Сразу оговорюсь, если Вы — профессионал в использовании регулярных выражений, то Вам лучше дальше не читать во избежание ^(.*)$

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

Результат, мягко говоря, удивителен. Вот вербальное выражение из README-файла репозитория для тестирования правильности URL:
<code class="cs">var tester = VerEx()
            .startOfLine()
            .then( "http" )
            .maybe( "s" )
            .then( "://" )
            .maybe( "www." )
            .anythingBut( " " )
            .endOfLine();
</code>

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

Основа проекта — JS-библиотека, но также имеется куча реализаций и на других языках.

Оригинал статьи.

P. S. Если кто-то уже использует эту библиотеку, пожалуйста, приведите пример сложной регулярки, написанной в данном стиле.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Из песочницы] Unreal LED, или управление нагрузкой из Unreal Tournament

Идея может показаться стёбом, но вполне заслуживает права на жизнь. Речь здесь пойдет о копировании событий из виртуальной реальности вовне, т. е. в направлении, обратном привычной репликации реальности в виртуальность. Я называю это «дополненной реальностью наоборот». Суть идеи заключается в отправке HTTP-запросов на Ethernet-шилд Arduino. Из UT.

Intro
Пожалуй, каждый покупатель Ethernet модуля или шилда делал из *дуино сервер включения светодиода, и многие рано или поздно пришивали его к какому-либо клиенту вроде смартфона на Android. Недавно меня посетила мысль — почему бы не использовать в роли этого клиента Unreal Tournament? UT — прекрасная визуализационная среда, а кроме того, сам движок очень удобен и гибок.

Знания редактора на уровне интерфейса достаточно. К исходникам на UnrealScript будут даны пояснения по ходу написания нашего клиента, а вообще UnrealScript имеет обычный сишный синтаксис со вполне понятными названиями функций. Тем, кто видит Unreal Editor в первый раз, но всё равно хочет попробовать, рекомендую прочесть статью VBKesha Знакомство с UnrealEngine. Часть 1, и честно говоря, я и сам очень жду продолжения этого курса, ибо в сетевой репликации, к примеру, я полный дундук. Всё моё оружие, сделанное для UT99, правильно работает только в режиме сингла/оффлайна.

Сервер
Вообще, предполагается, что читателю уже известно всё, что касается вопроса создания web-сервера на Arduino. Тем не менее, повторение — мать учения, поэтому на всякий случай привожу один из вариантов этого примера.

Описание сервераАппаратная часть представлена Ethernet-модулем или шилдом на ENC28J60, для постройки скетча применена библиотека Ether_28J60 от Dr. Monk. Она представляет собой обёртку для библиотеки Nuelectronics. Распаковываем архивы отсюда и отсюда в каталог %arduino%\libraries, берём пример WebRemote, меняем под свои нужды, собираем по схеме (для отдельного модуля):
Плата ENC28J60Arduino
SIMOSI (D11)
SOMISO (D12)
SCLSCK (D13)
RSTRESET
5V5V
GNDGND
CSD10
На D6 выводе Arduino светодиод (через резистор), анодом (плюсом) в сторону дуины, катодом в сторону земли.

Скетч у меня выглядит следующим образом:
<code class="cpp">#include "EtherShield.h"
#include "ETHER_28J60.h"

int outputPin = 6;

static uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
static uint8_t ip[4] = {192, 168, 0, 40};
static uint16_t port = 80;
ETHER_28J60 e;

void setup(){ 
  e.setup(mac, ip, port);
  pinMode(outputPin, OUTPUT);
}

void loop(){
  char* params;
  if (params = e.serviceRequest()){
    e.print("<H1>Web Remote</H1>");
    if (strcmp(params, "?cmd=on") == 0) digitalWrite(outputPin, HIGH);
     else if (strcmp(params, "?cmd=off") == 0) digitalWrite(outputPin, LOW);
    e.print("LED state: <br>");
    if(digitalRead(outputPin)==1) e.print("on");
     else e.print("off");
    e.print(".<br>");
    e.print("<A HREF='?cmd=on'>Turn on</A><br>");
    e.print("<A HREF='?cmd=off'>Turn off</A>");
    e.respond();
  }
}
</code>

Болванка
Для выполнения запроса нам потребуется класс клиента, которому можно передавать свои параметры во время выполнения. К счастью, такой класс там уже есть, называется он UBrowser.UBrowserHTTPClient. В UT2003/2004 пака UBrowser нет, зато есть UWeb.WebApplication и его субклассы. Рассмотрим отправку запроса из UT99, а под более старшие версии можно будет заточить по аналогии. UBrowserHTTPClient умеет делать только GET-запрос, но можно научить его и POST. Собственно, можно вообще любым образом изменять HTTP-заголовки, и реализовать не только протокол HTTP, но и какой-нибудь другой.

UBrowserHTTPClient не имеет визуального отображения в редакторе (меша или текстуры-спрайта) — если добавить его в уровень, он там появится, но редактор это никак не покажет. Поэтому создадим для него более удобную «обёртку», заодно наделив парой переменных, которые можно будет править на уровне. В качестве родителя (суперкласса) используем класс триггера.

Теперь продолжим то, о чём не было речи в статье VBKesha. Над рабочей областью с просмотрами (viewports) есть кнопки вызова обозревателей (выглядят они так: ). Нас интересует Actor Classes, открывается кнопкой, похожей на пешку (самая первая). Если в этом окне нет нижнего поля с чекбоксами, оно включается командой View -> Show packages из меню. Включить надо, оно понадобится, т. к. мы собираемся создать свой собственный пак со скриптами.

Обозреватель Actor Classes Создание класса

Чтобы создать тестовый триггер, который позволит нам управлять запросом, открываем в этом окне группу Triggers (принцип — как в редакторе реестра Windows), затем выделяем Trigger и нажимаем кнопку . Верхняя строка появившегося окна — имя файла с паком для создаваемого класса, нижняя — имя класса. Т. о., если нажать Enter, получится класс MyPackage.MyTrigger. Свой я назвал нехитро stdHTTPTrig.stdHTTPTrigger. Далее, пишем собственно код:

<code class="cpp">class stdHTTPTrigger expands Trigger;
var() string BrowseURL,BrowseArg;

function Touch(actor Other){
local UBrowserHTTPClient uhc;
	foreach allactors(class'UBrowserHTTPClient',uhc) uhc.destroy();
	uhc=spawn(class'UBrowserHTTPClient');
	if(uhc != none) uhc.Browse(browseurl,browsearg);
}
</code>
Редактор сценариев (куда писать исходник) открывается двойным щелчком по классу, и автоматически при создании класса; компиляция делается кнопкой (Compile changed scripts) в верхней части окна. Нажимать Compile ALL не советую — сначала UE будет долго думать, потом пожалуется на то, что не найдены некоторые классы (из-за того что прогружено только необходимое), а потом, скорее всего, сделает GPF и вывалится, либо наглухо повиснет и его понадобится снимать тремя пальцами. После компиляции пак нужно сохранить, для этого находим его имя (то, что писали в строке Package name) в нижней части окна Actor Classes, ставим напротив него флаг, и нажимаем кнопку . Кстати, если надо быстро подправить исходник и сохранить, удобно открывать окно обозревателя классов кнопкой , не вылезая из редактора сценариев (если последний развернут на весь экран).

Как видно, рассмотренный триггер действует достаточно грубо: уничтожает вообще всех акторов клиента в уровне (просто в целях экономии памяти), затем создает новый, и просматривает им указанный ресурс. После вызова browse() клиент не уничтожается, т. к. для работы ему требуется некоторое время. Метод browse() имеет два необязательных параметра: TCP порт и таймаут. Используя последний, можно отслеживать успешность запроса, оценивая таким образом доступность ресурса. Также, у этого клиента есть callback-функции для возврата ответа сервера и обработки ошибок. Чтобы задействовать эту возможность, требуется переопределить эти функции, то есть создать свой субкласс, родителем которого будет UBrowserHTTPClient.

Тестовый уровень 1
Тестовая комната состоит из двух триггеров, одного PlayerStart'а и источников света. Свойства BrowseURL у обоих одинаковы — это IP-адрес сервера. BrowseArg — параметр, состоящий из имени ресурса (косая черта /), и данных (знак вопроса и переменные), то есть у одного — /?cmd=on, у другого — /?cmd=off. Окно свойств открывается ПКМ на объекте -> properties, либо по F4. Если F4 не нажимается, надо нажать левой кнопкой мыши по любому просмотру. Нарисовав комнату, жмём F6, в открывшемся окне (свойства уровня) находим LevelInfo, там — DefaultGameType. Меняем на singleplayer и нажимаем Enter (подставится UnrealShare.SinglePlayer), иначе объявится орава ботов и будет мешать. Затем строим уровень (Rebuild geometry), сохраняем, запускаем. Палим из бластера по триггерам (по дефолту их радиус действия 40), наслаждаемся эффектом.


Получение ответа сервера
Теперь, заценив идею в общих чертах, можно переходить к разработке на чистовую. Если планируется назвать пак с новым классом так же, а старый «дубовый» триггер не нужен, выходим из редактора и делаем что-нибудь с файлом packname.u в каталоге %ut99%\system (packname — то, как мы назвали пак с классом, %ut99% — путь к Unreal Tournament): перемещаем в каталог old, например. Или сразу в корзину, благо он нам не понадобится. Запускаем редактор заново.

События на уровне

Движок U не имеет иного механизма создания событий, кроме обхода по очереди всех акторов с подходящими свойствами, и вызова надлежащих функций. Во всех разновидностях триггеров для этого используется свойство Tag — переменная типа name (имя объекта) и функции Trigger(), Untrigger(). Untrigger() предназначена для эффекта «уничтожения» события, например в раздвижных дверях. Посередине проёма ставится триггер, создающий событие, указанное в свойстве Tag муверов (Mover, или Moveable brush — перемещаемый браш, или кисть), образующих дверь, причем в свойстве InitialState (в группе Object) указывается TriggerControl — режим, специально предусмотренный для такого поведения. При вхождении игрока в радиус действия триггера у муверов вызывается функция Trigger(), при покидании радиуса — Untrigger(). В результате двери будут открываться только в то время, пока игрок находится в зоне действия триггера. Мы поступим аналогичным образом, преследуя 2 цели: удобство использования при постройке уровня, и совместимость.

В данном примере, фактически, проверяется только состояние включено/выключено. Делается это при помощи условия и функции нахождения подстроки в строке. Но ничто не мешает развить эту систему до вытаскивания из ответа сервера некого значения, скажем уровней PWM для RGB светодиодов. Однако следует учесть, что RGB светодиод требует данные в виде RGB, а для Unreal цвет придётся пересчитывать в HSB.

Новый триггер будет иметь 8 образцов строк, которые следует искать в ответе сервера, и столько же имён для создания/уничтожения событий в случае, если строка найдена/не найдена. При желании можно увеличить, убрать, и т. д. Для HTTP-ошибок предусмотрено только создание событий — IMHO, использование Untrigger в этом случае не нужно. Опять же, никто не запрещает добавить.

Открываем обозреватель классов (Actor Classes), в нем открываем группу Actor \ Info \ InternetInfo \ InternetLink \ TcpLink \ UBrowserBufferedTcpLink, выделяем класс UBrowserHTTPClient, нажимаем кнопку (New script). Указываем имя класса и пак, пишем код:

<code class="cpp">class stdHTTPBrowser expands UBrowserHTTPClient;

var string SearchRespData[8];
var name SearchRespEvent[8];
var name SearchNotInRespEvent[8];
var name SearchRespCancelEvent[8];
var name SearchNotInRespCancelEvent[8];
var int  HTTPErrCode[8];
var name HTTPErrEvent[8];

event HTTPReceivedData(string Data){
	local int i;
	local actor a;
	for(i=0;i<=7;i++){
		if(SearchRespData[i] != ""){
			if(InStr(Caps(Data),Caps(SearchRespData[i])) != -1){
				if(SearchRespEvent[i] != '')
					foreach allactors(class'Actor',a,SearchRespEvent[i])
						a.Trigger(self,self.instigator);
				if(SearchRespCancelEvent[i] != '')
					foreach allactors(class'Actor',a,SearchRespCancelEvent[i])
						a.Untrigger(self,self.instigator);
			}else{
				if(SearchNotInRespEvent[i] != '')
					foreach allactors(class'Actor',a,SearchNotInRespEvent[i])
						a.Trigger(self,self.instigator);
				if(SearchNotInRespCancelEvent[i] != '')
					foreach allactors(class'Actor',a,SearchNotInRespCancelEvent[i])
						a.Untrigger(self,self.instigator);
			}
		}
	}
}

event HTTPError(int Code){
	local int i;
	local actor a;
	for(i=0;i<=7;i++){
		if(HTTPErrCode[i] == Code && HTTPErrEvent[i] != '')
			foreach allactors(class'Actor',a,HTTPErrEvent[i])
				a.Trigger(self,self.instigator);
	}
}</code>
Тип name, IMHO, мало чем отличается от string, разве что есть localized string для строк на китайском, русском и т. п. Тем не менее, крайне важно: в условиях при проверке пустые имена равны '' (в одиночных кавычках), пустые строки — "" (в двойных кавычках). Ключевое слово event — то же самое что callback в сишных исходниках для Windows API. Короче, обратный вызов, т. е. функцию запускает не сценарий класса, а внешнее событие.

Предчувствуя комментарии сродни магазинчику Бо «во забрался в дыру», обрадую тем, что именно этот класс добавлять в уровень командой Add YourHTTPClientClass here мы не будем. За нас это будет делать функция spawn() в триггере. На мой взгдяд, это самый подходящий для таких вещей класс. Поэтому закрываем окно редактора сценариев, и в обозревателе классов открываем группу Actor \ Triggers и выделяем Trigger. Жмём New script и пишем код триггера:

<code class="cpp">class stdHTTPTriggerX expands Trigger;

var() enum EHTTPTriggerLaunchType{					// launch type
	HTTLT_Touch,
	HTTLT_Trigger
} HTTPTriggerLaunchType;
var() string SearchRespData[8];						// search template in HTTP response
var() name SearchRespEvent[8];						// events generated on match
var() name SearchNotInRespEvent[8];					// events generated if no match
var() name SearchRespCancelEvent[8];				// events cancelled on match
var() name SearchNotInRespCancelEvent[8];			// events cancelled if no match
var() int  HTTPErrCode[8];							// HTTP error templates
var() name HTTPErrEvent[8];							// events generated if defined HTTP error(s) ocurrs
var() string BrowseURL,BrowseArg;					// URL
var() bool bAutoExec;								// enable auto launch
var stdHTTPBrowser hClient;							// client handle

function CreateClientRequest(){
	local int i;
	if(hClient != none) hClient.destroy();			// destroy previous request
	hClient=spawn(class'stdHTTPBrowser');			// create
	if(hClient != none){
		for(i=0;i<=7;i++){
			hClient.SearchRespData[i]=self.SearchRespData[i];	// transfer configs
			hClient.SearchRespEvent[i]=self.SearchRespEvent[i];
			hClient.SearchNotInRespEvent[i]=self.SearchNotInRespEvent[i];
			hClient.SearchRespCancelEvent[i]=self.SearchRespCancelEvent[i];
			hClient.SearchNotInRespCancelEvent[i]=self.SearchNotInRespCancelEvent[i];
			hClient.HTTPErrCode[i]=self.HTTPErrCode[i];
			hClient.HTTPErrEvent[i]=self.HTTPErrEvent[i];
		}
		hClient.Browse(browseurl,browsearg);		// launch
	}
}

function Trigger(actor Other,pawn EventInstigator){	// triggered launch
	if(HTTPTriggerLaunchType == HTTLT_Trigger) CreateClientRequest();
}

function Touch(actor Other){						// proximity launch
	local actor a;
	if(IsRelevant(Other) && HTTPTriggerLaunchType == HTTLT_Touch){
		if(ReTriggerDelay > 0){
			if(Level.TimeSeconds-TriggerTime < ReTriggerDelay) return;
			TriggerTime=Level.TimeSeconds;
		}
		CreateClientRequest();
		if(Message != "") Other.Instigator.ClientMessage(Message);
		if(bTriggerOnceOnly) SetCollision(False);
	}
}

function PostBeginPlay(){							// autoexec launch
	if(bAutoExec) CreateClientRequest();
}</code>
Здесь уничтожается только тот объект клиента, который был создан этим триггером. Это обеспечивает одновременную работу нескольких клиентов. Ключевое слово none — пустое имя объекта, позволяет выяснить — создался объект или нет; self — имя собственного объекта, позволяет обратиться к самому себе. Выражение self. перед именем переменной можно не писать, но это делает код менее понятным. Скобки () после var обозначают, что эту переменную надо показывать в окне редактора свойств (Actor properties). То есть, класс клиента, хоть эти свойства имеет, но редактировать их можно только из сценария — у нас этим занимается цикл в CreateClientRequest(). IsRelevant() позаимствовано из класса Engine.Trigger для обеспечения совместимости с его свойствами. Условие с ReTriggerDelay позволяет сделать ограничение на срабатывание не чаще указанного интервала.

Компилируем (Compile changed scripts в редакторе сценариев), сохраняем пак в обозревателе.

Описание переменных

HTTPTriggerLaunchTypeТип запуска
SearchRespData[]Шаблоны для поиска
SearchRespEvent[]События, вызываемые при нахождении шаблона
SearchNotInRespEvent[]События, вызываемые при отсутствии шаблона
SearchRespCancelEvent[]События, уничтожаемые при нахождении шаблона
SearchNotInRespCancelEvent[]События, уничтожаемые при отсутствии шаблона
HTTPErrCode[]Коды HTTP ошибок
HTTPErrEvent[]События, вызываемые при HTTP ошибках
BrowseURLАдрес сервера
BrowseArgРесурс и параметры
bAutoExecАвтоматическое выполнение запроса при загрузке уровня
Если тип запуска HTTLT_Touch, триггер запустит CreateClientRequest() при вхождении определенного класса в свой радиус. При этом учитывается значение TriggerType (в группе Trigger): TT_AnyProximity — любой класс, TT_PawnProximity — любая пешка (игрок, бот или монстр), TT_PlayerProximity — только игрок, TT_ClassProximity — определённый класс (указывается в свойстве ClassProximityType), TT_Shoot — снаряд (субкласс Projectile) или попадание из оружия с моментальным действием, т. е. вызов функции TakeDamage() этого триггера. Порог ущерба (насколько больно сделать триггеру, чтобы тот сработал) указывается в свойстве DamageThreshold.
Если тип запуска HTTLT_Trigger, он запускается только по вызову функции Trigger, например при возникновении события, указанного в свойстве Tag (в группе Events).
Если bAutoExec равно true, триггер автоматически сделает запрос после начала игры. Это используется для первоначальной установки триггеров в соответствии с состоянием сервера, т. е. для синхронизации.

Тестовый уровень 2
Источник света в комнате с PlayerStart — обычный Light. Источник под потолком в комнате с триггерами — TriggerLight. Он дублирует состояние светодиода. Два других источника в этой же комнате просто подсвечивают панели. Сперва разместим TriggerLight. Выделяем его в Actor classes (находится в Actor \ Light), добавляем нажатием ПКМ по текстуре потолка и выбором Add TriggerLight here. У меня в обозревателе классов их почему-то два, работают оба, так что выбираем любой.
Свойства группы TriggerLight не трогаем, bInitiallyActive равно false, так и нужно. Открываем группу Object и меняем InitialState на TriggerControl. Если по щелчку на свойстве выпадающая менюшка не показывается (возможный баг под Win 7), мотаем стрелками влево/вправо с клавиатуры. Далее открываем группу Events, меняем Tag с None на какое-нибудь слово, у меня было lighton.

Триггеры добавляются аналогично (находится в Actor \ Triggers \ Trigger); панели можно не рисовать — я сделал, чтобы на видео было понятнее. Текстуры из Mine.utx.

Свойства триггеров приведены в таблице.
 HTTPTrigger0HTTPTrigger1HTTPTrigger2
bAutoExecFalseFalseTrue
BrowseArg/?cmd=on/?cmd=off/
BrowseURL192.168.0.40192.168.0.40192.168.0.40
HTTPTriggerLaunchTypeHTTLT_TouchHTTLT_TouchHTTLT_Trigger
SearchNotInRespCancelEvent[0]lightonlightonlighton
SearchRespEvent[0]lightonlightonlighton
SearchRespData[0]LED state: <br>onLED state: <br>onLED state: <br>on
Если планируется ловить ошибки сервера, просто пишем в свойствах HTTPErrCode[] их номера, например 404, 403, 302 и т. д.

Результат


Братюня уже один коммент под видео написал, просто сопровождал весь процесс. Видимо, ради хохмы решил нарисовать квартиру и привязать управление умным домом к любимому рубилову. Но разумеется, это не единственное применение GET-запроса. Можно, к примеру, сделать UT-сервак, который будет грузить для игроков карты с нужными атмосферными явлениями, в зависимости от показаний датчика. В общем, теперь можно сделать web-интерфейс по-настоящему красочным.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Django throttling

Как-то раз пришлось использовать чужое django-app, в котором было много форм, методов и всего остального. И, что само собой разумеется, автор решил не заморачиваться и не делать никакой защиты от спамеров, или от любителей понажимать F5 на тяжелой форме. Переписывать и форкать у меня желания не было, поэтому решил написать middleware, режущий кислород нехорошим людям.
Функционал
  • maintenance режим, позволяет выключать view в целом, или отдельные http методы
  • глобальные fallback-таймауты сайта для PATCH, POST и т.д.
  • локальные таймауты для view в целом, или для отдельных http-методов
Проще показать пример конфига:
<code class="python">DJANGO_THROTTLING = {
    'all': 1000,
    'post': 'callable:helpers.trash.my_callback',
    'congestion': 'forum.views.congestion',

    'django.contrib.admin.options.change_view': {
        'post': False,
        'all': None,
        'uri': '/admin/forum/post/23/',
    },
}
</code>
Остальные примеры с описанием под катом.


Установка

<code class="bash">git clone http://github.com/night-crawler/django-throttling.git
cd django-throttling
python setup.py install
</code>

Global throttling
Конфиг состоит из секций, самая верхняя — fallback, применяется для всего сайта в целом, в случае, если не нашлось более детализированного правила.

<code class="python">DJANGO_THROTTLING = {
    'all': 1000,
    'post': 10000,
    'congestion': 'forum.views.congestion',
}
</code>
В этом примере для запросов всех типов установлено ограничение в 1 запрос в секунду, post — запрос раз в 10 секунд.
congestion может быть uri, или вьюхой. В данном случае будет вызвана вьюха, живущая по соседству:

<code class="python">def congestion(request, congestion_bundle):
    user = request.user
    progress = int(float(congestion_bundle['delta']) / congestion_bundle['timeout'] * 100)
    c = Context({'user': user, 'congestion_bundle': congestion_bundle, 'progress': progress})
    return render_to_response(get_theme_template(user, 'congestion.html'), c,
        context_instance=RequestContext(request)
    )
</code>

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

Можно отключить POST на всем сайте. Тогда юзер увидит HttpResponseBadRequest:
<code class="python">DJANGO_THROTTLING = {
    'all': 1000,
    'post': False,
    'congestion': 'forum.views.congestion',
}
</code>

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

<code class="python">DJANGO_THROTTLING = {
    'all': 1000,
    'post': '/',
    'congestion': 'forum.views.congestion',
}
</code>

Если простого редиректа недостаточно, то можно сделать свой обработчик для maintenance-mode:
<code class="python">DJANGO_THROTTLING = {
    'all': 1000,
    'post': 'forum.views.maintenance',
    'congestion': 'forum.views.congestion',
}

# forum.views.maintenance
def maintenance(request, maintenance_bundle):
    return HttpPreResponse(maintenance_bundle)
</code>

Может быть так, что нужно блокировать вьюху только в определенных случаях, например, для блокирования одного топика в форуме, или для еще какого-то частного случая. Тогда можно написать кастомный обработчик для правила:
<code class="python">DJANGO_THROTTLING = {
    'all': 1000,
    'post': 'callable:helpers.trash.my_callback', # обратите внимание на callable:
    'congestion': 'forum.views.congestion',
}

# helpers.trash.my_callback'
def my_callback(request, view_func, view_args, view_kwargs):
    return 'some_strange_key_123', 10000
</code>
Он должен возвращать кортеж из названия ключа и таймаута. Таймаутом может снова быть int(), False, view, или uri.

Local throttling
В основном имеет аналогичный синтаксис. Отличается только наличием опционального ключа 'uri', который позволяет натравливать throttle check только на него.

<code class="python">DJANGO_THROTTLING = {
    'all': 1000,
    'post': 'callable:helpers.trash.my_callback',
    'congestion': 'forum.views.congestion',

    'django.contrib.admin.options.change_view': {
        'post': False,
        'all': None,
        'uri': '/admin/forum/post/23/',
        # 'post': 'callable:helpers.trash.my_callback',
        # 'all': 4000,
    },
}
</code>

Пупутно есть несколько настроек:

  1. DJANGO_THROTTLING_ENABLED: включает троттлинг, по умолчанию выключен.
  2. DJANGO_THROTTLING_CACHE_EXPIRE: определяет сколько хранятся ключи в кэше. По умолчанию 60*60.
  3. DJANGO_THROTTLING_CACHE_PREFIX: кэш-префикс, по умолчанию «THROTTLING»
  4. THROTTLING_CACHE_KEY_PATTERNS: тут хранятся паттерны для генерации ключа. Всего есть 4 разновидности: view_method, view, site_method, site. Можно переопределить.
  5. DJANGO_THROTTLING_IGNORE_ADMIN: выключает троттлинг, если пользователь — админ. Соответственно, требует подключенного auth

На github'е есть описание на «английском».

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Из песочницы] «Многопоточность» WSH VBScript

Костыль

Доброго всем времени суток. Предлагаю костыль, реализующий механизм многопоточности (а точнее «многопроцессности») для WSH VBScript. Не рекомендуется лицам с аллергией на индокод.
Первая мысль о потенциальных удобствах многопоточности пришла однажды во время решения на добровольных началах относительно несложной задачи по обработке и визуализации информации. И, поскольку установка IDE навроде Visual Studio и наш Helpdesk — понятия несовместимые, из «легальных» оставались только VBA и WSH. В то время был выбран последний. А действующие административные ограничения и желание получить дружественные методы продиктовали требования к данной реализации многопроцессности:
  • Код расположен в одном файле, как обычный сценарий.
  • Использует минимум ActiveX, и только встроенных, работоспособен без WMI, под WSH x86/x64.
  • Достаточная функциональность и удобство важнее быстродействия и паттернов.
Особенности:
  • Запущенный скрипт выполняет служебную функцию. Основной код выполняется в последующих процессах.
  • В «полной версии» основной код размещается только в классах, экземпляр любого из которых можно создать в отдельном процессе. В каждом новом процессе скрипт создает экземпляр служебного класса, который создает экземпляр указанного целевого класса, вызывает целевой метод, контролирует его ход, создает в глобальном контексте скриптов переменные, ссылающиеся на созданные экземпляры классов. В предшествующий скрипт возвращается объект инициализированного целевого класса, и «обрабатываются» события инициализации и завершения целевого класса запущенного скрипта.
  • В «легкой версии» логика аналогична, только основной код размещается внутри sub’ов, предшествующему скрипту возвращается не объект, а индекс запущенного, и нет обработки событий.
  • Для создания нового процесса скрипт рекурсивно запускает самого себя, передав данные о вызываемом методе и идентифицирующую информацию в именованном аргументе.
  • Единого пространства исполнения нет, каждый скрипт хранит свои данные и объекты в своем контексте. Для обмена данными объект Me первого скрипта передается в последующие с применением GlobalContainer, описанным в теме «обмен данными и объектами между скриптами — 2» на Сером форуме. Каждый скрипт после завершения целевого метода ожидает разрешения на завершение, такая задержка позволяет забрать из него полученную информацию.
  • Функционирует одинаково в WSH WScript и CScript, и в виде скомпилированного в ScriptCryptor exe-файла (правда, в exe не работают методы class_terminate).

Минусы:
  • Сложность в отладке из-за использования во многих методах on error resume next и execute. Все ж таки это костыль.
  • Громоздкость.
  • Порядок завершения скриптов полностью в ответственности разработчика. Естественно, при обращении к объектам завершенного скрипта возникнет ошибка.
Актуально:
  • Не реализованы мьютексы и механизмы залочивания метода от использования более чем одним процессом.
  • Возможны сбои при одновременном доступе к переменным скрипта из контекстов других.
  • Окно проводника остается в памяти при закрытии окна консоли CScript.exe.

Легкая версия mproclite.vbs:

<code class="vbscript">option explicit
launch "base"

' main programm section

sub base()
	startproc "msg"
	startproc "msg"
	startproc "msg"
	msgbox "base, id = " & id, 64
	free id
end sub

sub msg()
	msgbox "msg, id = " & id, 64
	free id
end sub

' do not modify service section

sub launch(byval destination)
	dim job
	executeglobal "dim scene, container, signature, subname, jobs, id, state, release"
	release = false
	if not wscript.arguments.named.exists("task") then
		dim elt
		executeglobal "dim found, lost"
		id = 0
		found = 0
		lost = 0
		signature = ""
		randomize
		do
			signature = signature & hex(rnd * 16)
		loop while len(signature) < 16
		set scene = me
		set jobs = createobject("Scripting.Dictionary")
		set jobs(0) = scene
		set container = getobject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}")
		container.putproperty signature, scene
		startproc destination
		on error resume next
		do until (lost >= found) or release
			for elt = found to 1 step -1
				if typename(jobs(elt)) = "Object" then
					lost = lost + 1
					jobs(elt) = empty
				end if
				err.clear
				wscript.sleep 1
			next
		loop
		release = true
		executeglobal "scene_beforeterminate"
		for elt = found to 1 step -1
			if typename(jobs(elt)) = "VBScriptTypeInfo" then
				jobs(elt).wscript.timeout = 1
				jobs(elt).wscript.quit
				err.clear
				nojobs = false
			end if
			wscript.sleep 1
		next
		container.quit
	else
		job = split(wscript.arguments.named("task"), ";")
		signature = cstr(job(0))
		id = clng(job(1))
		subname = cstr(job(2))
		do
			for each container in createobject("Shell.Application").windows
				if isobject(container.getproperty(signature)) then
					exit do
				end if
			next
			wscript.sleep 1
		loop
		set scene = container.getproperty(signature)
		set jobs = scene.jobs
		state = 4
		set jobs(id) = me
		executeglobal subname
		state = 24
		do until release
			wscript.sleep 10
		loop
		state = 28
	end if
end sub

function startproc(subname)
	startproc = createproc(subname)
	joint startproc, 4, 0
	REM do while getstate(startproc) < 4
		REM wscript.sleep 10
	REM loop
end function

function createproc(subname)
	if me is scene then
		if not release then
			found = found + 1
			createproc = found
			set jobs(createproc) = nothing
			createobject("WScript.Shell").exec("""" & wscript.fullname & """ """ & wscript.scriptfullname & """ ""/task:" & join(array(signature, createproc, subname), ";") & """")
		end if
	else
		createproc = scene.createproc(subname)
	end if
end function

function getjob(target)
	on error resume next
	if jobs.exists(target) then
		set getjob = jobs(target)
		if err.number = 0 then exit function
		err.clear
	end if
	set getjob = nothing
end function

sub share(varname, value)
	scene.newvar varname
	if isobject(value) then
		execute "set scene." & varname & " = value"
	else
		execute "scene." & varname & " = value"
	end if
end sub

sub newvar(varname)
	executecommand "dim " & varname
end sub

sub executecommand(command)
	executeglobal command
end sub

function getstate(target)
	dim elt
	if jobs.exists(target) then
		on error resume next
		set elt = jobs(target)
		getstate = elt.state
		if err.number <> 0 then
			if not(elt is nothing) then
				getstate = 64
			else
				getstate = 1
			end if
		end if
		set elt = nothing
	else
		getstate = 64
	end if
end function

function isresponsive(target)
	isresponsive = cbool(getstate(target) and 28)
end function

sub free(target)
	if jobs.exists(target) then
		on error resume next
		jobs(target).release = true
	else
		dim elt, subname
		for elt = scene.found to 1 step -1
			on error resume next
			subname = jobs(elt).subname
			if subname = target then
				free jobs(elt).id
			end if
			err.clear
		next
	end if
end sub

function joint(target, state, timeout)
	dim reftime
	reftime = timer
	on error resume next
	if jobs.exists(target) then
		if isnumeric(target) then
			do while getstate(target) < state
				if timeisout(timeout, reftime) then
					joint = false
					exit function
				end if
				wscript.sleep 10
			loop
		else
			dim elt, subname
			for elt = scene.found to 1 step -1
				subname = jobs(elt).subname
				err.clear
				if subname = target then
					do while getstate(target) < state
						if timeisout(timeout, reftime) then
							joint = false
							exit function
						end if
						wscript.sleep 10
					loop
				end if
				err.clear
			next
		end if
	end if
	joint = true
end function

function timeisout(timeout, reftime)
	if timeout > 0 then
		dim delta
		delta = timer - reftime
		if delta < 0 then delta = delta + 86400
		if delta > timeout then
			timeisout = true
		end if
	else
		timeisout = false
	end if
end function

sub interrupt(target, timeout)
	if jobs.exists(target) then
		on error resume next
		jobs(target).wscript.timeout = timeout
		jobs(target).wscript.quit
	else
		dim elt, subname
		for elt = scene.found to 1 step -1
			on error resume next
			subname = jobs(elt).subname
			if subname = target then
				interrupt jobs(elt).id
			end if
			err.clear
		next
	end if
end sub

sub push(name, value)
	container.putproperty name, value
end sub

function pop(name)
	on error resume next
	if isobject(container.getproperty(name)) then
		set pop = container.getproperty(name)
	else
		pop = container.getproperty(name)
	end if
end function</code>

Описание:

Функции механизма многопроцессности легкой версии:

launch subname
Запускает служебный алгоритм, выполнение скрипта всегда начинается с его вызова.
subname – строка, указывает целевой sub, который будет выполнен в новом процессе.
Аргументы этого метода используются только в первично запущенном скрипте для начала выполнения основного кода.
В каждом новом скрипте:
  • Объявляются переменные в глобальном пространстве запущенного скрипта:
    scene – ссылка на объект Me первого скрипта,
    container – ссылка на окно проводника GlobalContainer,
    signature – строка, сгенерирована для идентификации GlobalContainer,
    found, lost – только для scene – счетчики созданных и завершенных процессов скриптов,
    subname – строка, содержит цель скрипта,
    jobs – ссылка на словарь с объектами Me запущенных скриптов, созданный в scene,
    id – порядковый номер данного скрипта — ключ в словаре,
    release = Ложь — после завершения целевого sub’а скрипт будет завершен после присвоения Истина,
    state = 4 – состояние, в котором находится данный скрипт.
  • Добавляется элемент в словарь jobs.
startproc(subname)
subname – см. launch().
Создает новый процесс скрипта, ожидает его готовности до состояния 4 (см. getstate()), когда можно обращаться к объекту Me скрипта. Возвращает число — id запущенного скрипта.

createproc(subname)
subname – см. launch().
Создает новый процесс скрипта, не ожидая, возвращает число — id запущенного скрипта. Используется для асинхронного создания нескольких процессов в цикле, без ожидания готовности каждого. Заметно быстрее по сравнению с использованием startproc() для такого применения.

getjob(target)
target – число, id скрипта или строка, имя subname группы созданных скриптов.
Обеспечивает доступ к объекту Me скрипта. Возвращает ссылку на объект Me скрипта, если id не найден или скрипт завершен – Nothing.

getstate(target)
target – число, id скрипта.
Определяет состояние скрипта. Возвращает число, этап выполнения:
1 процесс создан (new process exec),
4 скрипт запущен (initialized),
24 целевой sub выполнен (sub completed),
28 скрипт освобожден (released),
64 не найден (host not found), скрипт завершен (terminated).

isresponsive(target)
target — см. getstate().
Определяет доступность объекта Me скрипта (состояния с 4 по 28). Возвращает булево значение.

executecommand command
command — строка, содержащая инструкции.
Вызов интерпретатора для выполнения операторов в глобальном пространстве скрипта.

share varname, value
varname — строка, содержащая имя переменной, value – любое значение.
Объявляет в глобальном пространстве первого скрипта переменную с именем varname, которая становится доступна всем скриптам в виде свойства scene, присваивает переменной содержимое value.

newvar varname
varname — строка, содержащая имя переменной.
Объявляет новую переменную в глобальном пространстве скрипта.

free target
target – число, id скрипта или строка, имя subname группы созданных скриптов. Разрешает завершение скрипта после выполнения целевого sub’а. Работает с одним скриптом или с группой.

joint(target, state, timeout)
target — см. free(), state — см. getstate(), timeout – число, в секундах, с миллисекундами.
Ожидает наступления состояния скрипта state, для группы скриптов ожидание длится, пока каждый не достигнет state. Ожидание ограничено таймаутом, timeout = 0 означает неограниченное ожидание. Возвращает булево значение, Истина – ожидание закончено, Ложь – таймаут. Предназначен для синхронизации работы скриптов. Например, если необходимо дождаться запуска скрипта — 4, полного завершения скрипта — 64;

interrupt target, timeout
target — см. free(), timeout – значение для wscript.timeout, в секундах.
Переводит скрипт к штатному завершению, с выполнением методов class_terminate. Если в скрипте были открыты диалоговые окна, он перейдет к завершению только после паузы timeout. Повторное появление диалогового окна в методах class_terminate остановит завершение.

push name, value
name – строка, имя свойства, value – любое значение.
Помещает в свойство GlobalContainer с именем name содержимое value.

pop(name)
name – строка, имя свойства.
Возвращает из GlobalContainer содержимое свойства с именем name.

Полная версия mproc.vbs:

<code class="vbscript">option explicit
dim mproc
set mproc = new multiprocess
mproc.launch "base", "run", ""

' main programm section

class base
	
	public sub run()
		host.startproc "msg", "run", "first"
		host.startproc "msg", "run", "second"
		host.startproc "msg", "run", "third"
		msgbox "base, id = " & host.id, 64
		host.free host.id
	end sub
	
end class

class msg
	
	public sub run()
		msgbox host.aliasname & ", id = " & host.id, 64
		host.free host.id
	end sub
	
end class

' do not modify service class section

class multiprocess
	
	public primary, ancestor, parent, process, err
	public names, execs, hosts
	public id, aid, isprimary
	public classname, methodname, aliasname
	public found, lost, active
	public state, permit, release
	private container, signature, wshshell
	
	public sub launch(startclassname, startmethodname, startaliasname)
		permit = false
		release = false
		executeglobal "dim scene, host, ancestor, process"
		if not isempty(host) then exit sub
		set host = me
		executeglobal "set host.err = err"
		executeglobal "function getroot: set getroot = me: end function"
		set parent = getroot
		isprimary = not wscript.arguments.named.exists("task")
		if isprimary then
			dim sample
			state = 24
			randomize
			signature = ""
			do
				signature = signature & hex(rnd * 16)
			loop while len(signature) < 16
			aid = empty
			id = 0
			found = 0
			lost = 0
			set wshshell = createobject("WScript.Shell")
			set primary = host
			set ancestor = nothing
			set process = nothing
			set scene = parent
			set parent.ancestor = nothing
			set parent.process = nothing
			set hosts = createobject("Scripting.Dictionary")
			set execs = createobject("Scripting.Dictionary")
			set names = createobject("Scripting.Dictionary")
			classname = empty
			methodname = empty
			aliasname = empty
			set hosts(0) = host
			set container = getobject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}")
			container.putproperty signature, parent
			startproc startclassname, startmethodname, startaliasname
			on error resume next
			do
				for each sample in execs.keys
					if release or active = 0 then exit do
					if not (execs(sample) is nothing) then
						if execs(sample).status > 0 then
							abolish sample
						end if
					end if
					wscript.sleep 1
				next
			loop
			release = true
			state = 28
			scenequit
		else
			dim job
			job = split(wscript.arguments.named("task"), ";")
			signature = cstr(job(0))
			do
				for each container in createobject("Shell.Application").windows
					if isobject(container.getproperty(signature)) then
						exit do
					end if
				next
				wscript.sleep 1
			loop
			aid = clng(job(1))
			id = clng(job(2))
			found = null
			lost = null
			set scene = container.getproperty(signature)
			set primary = scene.host
			set hosts = primary.hosts
			set ancestor = hosts(aid)
			if isresponsive(aid) then
				set parent.ancestor = ancestor.parent.process
			else
				set parent.ancestor = nothing
			end if
			classname = cstr(job(3))
			methodname = cstr(job(4))
			aliasname = cstr(job(5))
			state = 4
			primary.implicate id, aliasname, host
			executeglobal "set process = new " & classname
			executeglobal "set host.process = process"
			executeglobal "set scene." & aliasname & " = process"
			if isresponsive(aid) then
				executeglobal "set host.ancestor.parent." & aliasname & " = process"
			end if
			state = 8
			primary.staff host
			ancestorevent "oninitialized"
			state = 12
			if methodname <> "" then
				do until permit
					wscript.sleep 10
				loop
				state = 16
				executeglobal "process." & methodname
			end if
			state = 20
			ancestorevent "oncompleted"
			state = 24
			do until release
				wscript.sleep 10
			loop
			state = 28
		end if
	end sub
	
	public default function startproc(classname, methodname, aliasname)
		set startproc = start(createproc(classname, methodname, aliasname))
	end function
	
	public function createproc(classname, methodname, aliasname)
		if aliasname = "" then aliasname = classname
		newvar aliasname
		scene.host.newvar aliasname
		createproc = primary.spawn(id, classname, methodname, aliasname)
	end function
	
	public function spawn(issuer, classname, methodname, aliasname)
		if not release then
			found = found + 1
			spawn = found
			active = found - lost
			names(spawn) = aliasname
			set hosts(spawn) = nothing
			if not hosts.exists(aliasname) then
				hosts.add aliasname, createobject("Scripting.Dictionary")
			end if
			set hosts(aliasname)(spawn) = nothing
			execs.add spawn, wshshell.exec("""" & wscript.fullname & """ """ & wscript.scriptfullname & """ ""/task:" & join(array(signature, issuer, spawn, classname, methodname, aliasname), ";") & """")
		end if
	end function
	
	public function start(target)
		select case outline(target)
		case "Nothing", "multiprocess"
			do while getstate(target) < 12
				wscript.sleep 10
			loop
			if isresponsive(target) then
				set start = hosts(target).process
				hosts(target).permit = true
			else
				set start = nothing
			end if
		case "Dictionary"
			dim elt
			set start = hosts(target)
			for each elt in start.keys
				do while getstate(elt) < 12
					wscript.sleep 10
				loop
			next
			for each elt in start.keys
				if isresponsive(elt) then
					hosts(elt).permit = true
				end if
			next
		case else
			set start = nothing
		end select
	end function
	
	public sub implicate(id, aliasname, host)
		set hosts(aliasname)(id) = host
		set hosts(id) = host
	end sub
	
	public sub staff(host)
		set hosts(host.process) = host
	end sub
	
	public sub abolish(id)
		if hosts.exists(names(id)) then
			hosts(names(id))(id) = empty
		end if
		names(id) = empty
		if isresponsive(id) then
			hosts(hosts(id).process) = empty
		end if
		hosts(id) = empty
		set execs(id) = nothing
		lost = lost + 1
		active = found - lost
	end sub
	
	private sub ancestorevent(eventname)
		if aid > 0 then
			on error resume next
			executeglobal "ancestor." & aliasname & "_" & eventname & " host.hosts(" & id & ")"
			if err.number = 424 or err.number = 438 then err.clear
		end if
	end sub
	
	public sub assignhandler(handlername, byval varsqty)
		dim vars
		vars = ""
		if varsqty > 0 then
			do
				vars = vars & "param" & varsqty
				varsqty = varsqty - 1
				if varsqty = 0 then exit do
				vars = vars & ", "
			loop
		end if
		executeglobal "sub " & handlername & "(" & vars & "): process." & handlername & " " & vars & ": end sub"
	end sub
	
	public sub newvar(varname)
		executecommand "dim " & varname
	end sub
	
	public sub executecommand(command)
		executeglobal command
	end sub
	
	public function getstate(target)
		select case outline(target)
		case "multiprocess"
			on error resume next
			getstate = hosts(target).state
			if err.number <> 0 then
				err.clear
				getstate = 64
			end if
		case "Nothing"
			getstate = 1
		case "Dictionary"
			getstate = null
		case empty
			getstate = 0
		case else
			getstate = 64
		end select
	end function
	
	private function outline(target)
		on error resume next
		if hosts.exists(target) then
			outline = typename(hosts(target))
			if err.number <> 0 then
				err.clear
				outline = "Object"
			end if
		else
			outline = empty
		end if
	end function
	
	public function isresponsive(target)
		isresponsive = cbool(getstate(target) and 28)
	end function
	
	public function getid(target)
		on error resume next
		if isobject(target) then
			if isresponsive(target) then
				getid = hosts(target).id
				if err.number = 0 then exit function
				err.clear
			end if
		elseif primary.execs.exists(target) then
			getid = target
			exit function
		end if
		getid = null
	end function
	
	public function gethost(target)
		on error resume next
		if hosts.exists(target) then
			set gethost = hosts(target)
			if err.number = 0 then exit function
			err.clear
		end if
		set gethost = nothing
	end function
	
	public sub free(target)
		select case outline(target)
		case "multiprocess"
			on error resume next
			gethost(target).release = true
			err.clear
		case "Dictionary"
			dim elt
			for each elt in gethost(target)
				free(elt)
			next
		end select
	end sub
	
	public function joint(target, state, timeout)
		dim reftime
		reftime = timer
		select case outline(target)
		case "multiprocess", "Nothing"
			do while getstate(target) < state
				if timeisout(timeout, reftime) then
					joint = false
					exit function
				end if
				wscript.sleep 10
			loop
		case "Dictionary"
			dim elt
			for each elt in gethost(target)
				do while getstate(elt) < state
					if timeisout(timeout, reftime) then
						joint = false
						exit function
					end if
					wscript.sleep 10
				loop
			next
		end select
		joint = true
	end function
	
	private function timeisout(timeout, reftime)
		if timeout > 0 then
			dim delta
			delta = timer - reftime
			if delta < 0 then delta = delta + 86400
			if delta > timeout then
				timeisout = true
			end if
		else
			timeisout = false
		end if
	end function
	
	public sub interrupt(target, timeout)
		select case outline(target)
		case "multiprocess"
			on error resume next
			with gethost(target).parent
				.wscript.timeout = timeout
				.wscript.quit
			end with
			err.clear
		case "Dictionary"
			dim elt
			for each elt in gethost(target)
				interrupt elt, timeout
			next
		end select
	end sub
	
	public sub kickout(target)
		if primary.execs.exists(target) then
			if getstate(target) < 64 then
				on error resume next
				primary.execs(target).terminate
				err.clear
			end if
		else
			select case outline(target)
			case "multiprocess"
				kickout getid(target)
			case "Dictionary"
				dim elt
				for each elt in gethost(target)
					kickout(elt)
				next
			end select
		end if
	end sub
	
	public sub terminate(target)
		interrupt target, 1
		if not joint(target, 64, 2) then kickout target
	end sub
	
	public sub push(name, value)
		container.putproperty name, value
	end sub
	
	public function pop(name)
		on error resume next
		if isobject(container.getproperty(name)) then
			set pop = container.getproperty(name)
		else
			pop = container.getproperty(name)
		end if
	end function
	
	private sub scenequit
		if isprimary then
			dim col, i, status
			col = execs.keys
			for i = ubound(col) to 0 step -1
				interrupt col(i), 1
			next
			wscript.sleep 2000
			on error resume next
			for i = ubound(col) to 0 step -1
				status = execs(col(i)).status
				if err.number = 0 and status = 0 then execs(col(i)).terminate
				err.clear
			next
			container.quit
		end if
	end sub
	
	private sub class_terminate()
		if state < 28 and isprimary then scenequit
	end sub
	
end class
</code>

Описание:

Методы класса multiprocess:

launch classname, methodname, aliasname
Запускает служебный алгоритм, выполнение скрипта всегда начинается с его вызова.
classname, methodname, aliasname – строки. Указывают целевой класс classname и метод этого класса methodname, который будет выполнен в новом процессе, экземпляр класса classname будет помещен в переменную с именем aliasname (или classname, если aliasname – пустая строка).
Аргументы этого метода используются только в первично запущенном скрипте для начала выполнения основного кода.
В каждом новом скрипте:
  • Объявляются переменные в глобальном пространстве запущенного скрипта:
    scene – ссылка на объект Me первого скрипта,
    host – экземпляр класса multiprocess данного скрипта,
    process – экземпляр целевого класса с именем classname, которое было указано предшествующим скриптом при создании процесса данного скрипта,
    ancestor – экземпляр целевого класса предшествующего скрипта.
  • Объявляются переменные в глобальном пространстве scene и предшествующего скрипта, с именем aliasname – ссылки на экземпляр целевого класса данного скрипта.
  • Задаются свойства host:
    primary – ссылка на экземпляр класса multiprocess первого скрипта,
    ancestor – ссылка на экземпляр класса multiprocess предшествующего скрипта,
    parent – объект Me данного скрипта,
    process – ссылка на process в глобальном пространстве,
    err – ссылка на объект err данного скрипта,
    names – ссылка на словарь с aliasname, созданный в primary,
    execs – ссылка на словарь с объектами wshexec запущенных процессов, созданный в primary,
    hosts – ссылка на словарь с объектами host запущенных процессов, созданный primary,
    id – порядковый номер данного скрипта — ключ в словарях,
    aid – то же, предшествующего скрипта,
    isprimary – булево, является ли данный скрипт первично запущенным,
    found, lost, active – только для primary – счетчики созданных, завершенных и активных процессов скриптов,
    classname, methodname, aliasname – содержат цель скрипта,
    permit = Ложь — целевой метод будет запущен после присвоения Истина,
    release = Ложь — после завершения целевого метода скрипт будет завершен после присвоения Истина,
    state = 4 – состояние, в котором находится данный скрипт.
  • Добавляются элементы в словари names, execs, hosts.
startproc(classname, methodname, aliasname)
classname, methodname, aliasname – см. launch().
Создает новый процесс скрипта, ожидает его готовности до состояния 12 (см. getstate()), запускает целевой метод. Возвращает ссылку на инициализированный в новом процессе экземпляр целевого класса.

createproc(classname, methodname, aliasname)
classname, methodname, aliasname – см. launch().
Создает новый процесс скрипта, не ожидая, возвращает его id. Используется для асинхронного создания нескольких процессов в цикле, без ожидания готовности каждого. Заметно быстрее по сравнению с использованием startproc() для такого применения.

start(target)
target – число, id скрипта, или строка, имя aliasname группы созданных скриптов.
Ожидает готовности скрипта, созданного с использованием createproc(), до состояния 12, разрешает выполнение целевого метода. Возможно использование для группы скриптов, имеющих одинаковый aliasname. Для одного скрипта возвращает ссылку на его инициализированный в новом процессе экземпляр целевого класса, для группы скриптов возвращает ссылку на субсловарь, содержащий все host с данными aliasname.

gethost(target)
target – число, id скрипта или строка, имя aliasname группы созданных скриптов, или объект process скрипта.
Обеспечивает доступ к экземпляру host класса multiprocess требуемого скрипта. Для одного скрипта возвращает ссылку на его host, для группы скриптов возвращает ссылку на субсловарь, содержащий все host с данными aliasname, если id не найден или скрипт завершен – Nothing.

getid(target)
target – число, id скрипта, или объект process скрипта.
Возвращает id срипта, определенное по объекту process. Только для действующих скриптов.

getstate(target)
target — см. getid().
Определяет состояние скрипта. Возвращает число, этап выполнения:
0 не найден (host not found),
1 процесс создан (new process exec),
4 host инициализирован (host initialized),
8 целевой класс инициализирован (process initialized),
12 целевой класс инициализирован, событие обработано (process initialized handled),
16 целевой метод запущен (process method launched),
20 целевой метод выполнен (process completed),
24 целевой метод выполнен, событие обработано (process completed handled),
28 скрипт освобожден (released),
64 скрипт завершен (terminated).

isresponsive(target)
target — см. getid().
Определяет доступность объекта host скрипта (состояния с 4 по 28). Возвращает булево значение.

assignhandler handlername, varsqty
handlername — строка, имя события, varsqty — число, количество передаваемых аргументов.
Создает в глобальном пространстве хэндлер события sub с именем события handlername, связывет его с одноименным методом в созданном объекте process. При наступлении события, хэндлер перенаправит вызов в process. handlername().

executecommand command
command — строка, содержащая инструкции.
Вызов интерпретатора для выполнения операторов в глобальном пространстве скрипта.

newvar varname
varname — строка, содержащая имя переменной.
Объявляет новую переменную в глобальном пространстве скрипта.

free target
target — см. gethost().
Разрешает завершение скрипта после выполнения целевого метода. Работает с одним скриптом или с группой.

joint(target, state, timeout)
target — см. gethost(), state — см. getstate(), timeout – число, в секундах, с миллисекундами.
Ожидает наступления состояния скрипта state, для группы скриптов ожидание длится, пока каждый не достигнет state. Ожидание ограничено таймаутом, timeout = 0 означает неограниченное ожидание. Возвращает булево значение, Истина – ожидание закончено, Ложь – таймаут. Предназначен для синхронизации работы скриптов. Например, если необходимо дождаться создания объекта process — 8, полного завершения скрипта — 64;

interrupt target, timeout
target — см. gethost(), timeout – значение для wscript.timeout, в секундах.
Переводит скрипт к штатному завершению, с выполнением методов class_terminate. Если в скрипте были открыты диалоговые окна, он перейдет к завершению только после паузы timeout. Повторное появление диалогового окна в методах class_terminate остановит завершение.

kickout target
target — см. gethost().
Завершает процесс скрипта на уровне ОС, используя wshexec.terminate. Возможно длительное выполнение, до 2 сек для каждого скрипта. Работает с одним скриптом или с группой.

terminate target
target — см. gethost().
Завершает скрипт, использует сначала interrupt, затем при необходимости kickout.

push name, value
name – строка, имя свойства, value – любое значение.
Помещает в свойство GlobalContainer с именем name содержимое value.

pop(name)
name – строка, имя свойства.
Возвращает из GlobalContainer содержимое свойства с именем name.

Методы, которые можно разместить в целевом классе данного скрипта в качестве хэндлеров событий инициализации целевого класса и выполнения целевого метода запущенного скрипта:

<aliasname>_ oninitialized(source)
source – передаваемый в метод объект host скрипта, вызвавшего метод, его aliasname содержится в имени метода. Метод вызывается после инициализации целевого класса запущенного скрипта (state = 8).

<aliasname>_ oncompleted(source)
source — передаваемый в метод объект host скрипта, вызвавшего метод, его aliasname содержится в имени метода. Метод вызывается после выполнения целевого метода запущенного скрипта (state = 20).

Пример:

Для mproclite и mproc демонстрируется работа на примере абстрактной задачи: для каждого символа из строки letters создаются отдельные процессы, каждый в цикле помещает свой символ в буфер, по мере заполнения которого другой процесс выводит по 3 «слова» в консоль. Для WScript консоль сымитирована окном IE. Попутно выводятся запущенные и остановленные процессы ОС (в примере используется WMI, но для функционирования механизма он не обязателен).
В ходе дебага у меня накопились некоторые наблюдения и комменты, коими я поделюсь, если будет спрос — дело в том, что потребуется время, чтобы привести их в читабельный вид. Конструктивная критика приветствуется.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Windows Store c точки зрения разработчика


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

Как один из самих молодых магазинов приложений Windows Store, по идее, должен был бы впитать в себя самое лучшее из Google Play и App Store. Но на практике оказалось, что этого не случилось.

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

Налоговая декларация (Tax Profile)Для того чтобы начать продавать платные приложения не обходимо заполнить налоговую декларацию. Форму можно заполнить в онлайн: отправлять обычной почтой или факсом ее никуда не нужно. Вся соль не в этом. После заполнения формы вы сможете увидеть следующий живописный вид:


Попробуйте догадаться, что означает надпись: «Ваша налоговая декларация заполнена неправильно. Пожалуйста, исправьте ошибки».



После 3 неудачных заполнений формы пришлось спросить у Google, почему моя форма неправильна. На форуме нашлась подсказка. Надпись «Ваша налоговая декларация заполнена неправильно. Пожалуйста, исправьте ошибки» на самом деле означает следующее «Мы получили вашу форму и проверим ее в ближайшее время» (Ну и как с первого раза не догадаться). И действительно на следующий день возле нее появилась надпись Valid.

Добавляем приложениеНажав на кнопочку «Добавить приложение» (Submit an app) появляется очень приятный экран, где обозначены все шаги, которые нужно сделать.



Имя приложенияКак по мне сделано не очень логично. Имя приложения необходимо указать при сборке приложения в Visual Studio. Если у вас название локализируется на разные языки перевод необходимо указывать во время сборки. Потом все название, которые вы указали во время сборки необходимо вручную зарезервировать на вкладке имя приложения. Если же вы забудете зарезервировать одно из названий, то пакеты приложения у вас не примут по причине того, что название не зарегистрировано.

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



In-App покупкиНа дворе 2013 год, а Windows Store не умеет делать Consumable покупки (покупки которые можно совершать неограниченное количество раз: игровая валюта, подсказки, и.т.д.). Зато он умеет делать покупки со сроком годности. Мне их предназначение не совсем понятно, это и не совсем подписка. Но именно благодаря им разработчики смогли использовать костыль для продажи «монеток». Вместо товара 100_coins, забивается товар 100_coins.1, 100_coins.2, … сроком на один день. И эти товары продаются по кругу.


Игровые сертификаты Совсем отдельная песня. Хотя имеет отношение только к играм, но внимание обратить стоит. Есть страны для распространения, в которых необходимо предоставить сертификат, подтверждающий минимальный возврат игрока.
Тут было выбрано наихудшее решение. Если вы забудете загрузить сертификат, например для Бразилии, но при этом случайно отметили ее в списке стран для распространения, то об ошибке вы узнаете только через пять дней после проверки приложения. Почему это самое наихудшее решение?



Решить его можно было другими способами. Во-первых, при отсутствии сертификата предложить поставить возраст 18+ для той страны, как, например, делает Samsung Apps Store. Во-вторых, при отсутствии сертификата запретить отправку на проверку, пока не будет загружен сертификат или снята галочка.

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

Список языков сделан «очень» удобно. Попробуйте быстро найти, для какого языка описание не было закончено?



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

Теперь об оформлении. Для приложения можно указать ключевые особенности. По одной особенности в одно поле ввода. К сожалению, никто не подумал, что сочинять текст и переводить будут не при заливке приложения, а предварительно. И копировать каждую строчку в отдельное поле не самое интересное занятие.



То же самое касается и тегов.



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

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

Ну и вместо завершения, Windows Store не любит адрес электронной почты с плюсиком, а зря.



ЗавершениеЯ б не мог бы сказать, что я смог получить удовольствие во время прохождения квеста: опубликуй приложение в Windows Store. Меня преследовало такое чувство, что разработчиков здесь не любят.

Если я про что-то забыл, или что-то слишком непонятно описал, то с удовольствием отвечу на вопросы в комментариях. Если читателю интересно прочитать схожую статью про другие магазины приложений: Google Play, iTunes, Samsung Store, Amazon Store, то также жду пожеланий в комментариях.


Вы собираетесь публиковать свои приложения в Windows Store?


Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста. Проголосовало 45 человек. Воздержалось 12 человек. Источник: habrahabr.ru,
получено с помощью rss-farm.ru




Да, они уже там



Возможно в будущем



Нет

The Pirate Bay исполнилось 10 лет, и они запустили браузер для обхода цензуры



На днях, 9 августа, файлообменнику The Pirate Bay исполнилось 10 лет. Их сайт, как и многие другие, даже более легальные, заблокированы государственной цензурой во многих странах. TPB часто оказывается в списках запрещенных сайтов, поэтому на свой юбилей они представили новый браузер — Pirate Browser, который позволяет обходить цензуру, например в таких странах как Иран, Северная Корея, Великобритания, Голландия, Бельгия, Дания, Италия и т.д. При этом серфинг не становится анонимным: PirateBrowser направлен в первую очередь на предоставление доступа ко всей информации и сайтам Интернета как можно большему количеству людей во всем мире.

Браузер представляет собой настроенную сборку Tor client (Vidalia) и FireFox Portable browser (с аддоном foxyproxy).
Пока есть только версия для Windows, но вскоре ожидается выход версий для Mac и Linux.

Страница проекта, magnet-ссылка на дистрибутив, торрент-файл, прямая ссылка на архив.

PS Кстати, не так давно правительство США тратило миллионы долларов на проект, который должен был помочь справляться с государственной цензурой сайтов и сотовых сетей в разных странах.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Дайджест интересных материалов из мира веб-разработки и IT за последнюю неделю №69 (4 — 10 августа 2013)

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



Горячая семерка
Emmet LiveStyle
Встречаем Emmet LiveStyle — бета версию плагина нового поколения для двунаправленного редактирования CSS от Сергея Чикуенка, плюс Обзор LiveStyle на smashingmagazine (восторженные комментарии included)
Адаптивный дизайн
Статья о том, как Как тестировать адаптивный дизайн не тратясь на платные инструменты , а также небольшая подборка уроков
WebGL
WebGL продолжает развиваться, демонстрируя все большие возможности. Вот некоторые из них: 3d эффекты на страницах , рендер более миллиона частиц, и напоследок, действительно впечатляющая демка, показывающая потенциал создания игр с помощью WebGL
Проблемы CSS
Перевод занимательной статьи о проблемах CSS, про которые обычно не вспоминают в учебниках по верстке. Часть 1, Часть 2
Firefox 23
На этой неделе состоялся Релиз Firefox 23. Кроме небольшого изменения в логотипе, релиз включил в себя довольно приличное количество улучшений и добавлений, среди которых долгожданный network monitor
Почему Angular.js рулит?
Этой объемной статьей от Jesus Rodriguez старается дать аргументированный ответ на вопрос
YotaPhone
Отечественный телефон с двумя экранами уже успел пошуметь на выставках электроники. Более подробно о самом устройстве и особенностях его разработки, а в частности об истории его создания можно почитать в в первом официальном Йотафон-посте на Хабре

Веб-разработка
CSS
JavaScripts
Браузеры
Новости
Сервисы
Демо
Сайты с интересным дизайном и функциональностью
Дизайн
Подборка бесплатных дизайнерских печенек
Занимательное

Дайджест за прошлую неделю.
Материал подготовили dersmoll и alekskorovin

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Обама пообещал сделать программы разведки более прозрачными

image

Президент США Барак Обама вчера провёл в Белом доме пресс-конференцию, где объявил о четырёх реформах, которые, по его словам, повысят прозрачность и информированность общества о программах АНБ и других американских разведслужб, пишет The Verge.

«Мне, как президенту, недостаточно быть уверенным в этих программах, американский народ тоже должен быть в них уверен», — заявил Обама. «Другим людям со всего мира я хочу ещё раз ясно дать понять, что Америка не заинтересована в шпионаже за обычными людьми. Наша разведка ориентирована прежде всего на поиск информации, необходимой для защиты нашего народа, и во многих случаях для защиты наших союзников».

Как заявил Обама: «Это верно, что у нас есть значительные возможности. То, что также верно, это что мы способны к самоконтролю, о котором многие правительства по всему миру даже не думают». Он сказал, что анонсированные реформы задуманы по итогам бесед, которые он имел с членами конгресса и защитниками гражданских свобод, обеспокоенными активностью разведки, раскрытой в результате утечки документов от бывшего подрядчика АНБ Эдварда Сноудена.

«Учитывая историю злоупотреблений со стороны правительства, задавать вопросы по поводу разведки — это правильно», — сказал Обама. «Тем более, что технологии меняют каждый аспект нашей жизни». Президент также отметил, что в то время как критики разведки являются патриотами, «Я не думаю, что мистер Сноуден патриот», и правительство всё ещё обвиняет его в совершении трёх преступлений. Но он добавил: «Нет сомнений, что утечка от мистера Сноудена вызвала быструю и гораздо более эмоциональную реакцию».

Итак, четыре предложенные реформы:

  • Изменение раздела 215 Патриотического акта, который является частью законодательства, позволяющего АНБ собирать данные о телефонных разговорах всех клиентов американских сотовых операторов. Президент не уточнил, какие изменения будут внесены, ограничившись словами о «большем контроле, большей прозрачности и ограничении на использование этой власти», но сказал, что будет работать с конгрессом над изменением закона. В рамках немедленных мер Белый дом ?? выпустил документ с подробным описанием своего толкования раздела 215.
  • Реформирование Суда США по делам о надзоре за иностранными разведками (суд FISA), рассматривающего запросы АНБ на отслеживание сотовой связи и Интернета. В суде будет представлен защитник, который будет оспаривать эти запросы от имени общества. Как признался Обама, ранее суд заслушивал только «одну сторону дела» — правительство. Белый дом также пообещал обнародовать решение суда FISA 2011 года, которое определило некоторый шпионаж неконституционным, и собирается отправить его 12 августа в Electronic Frontier Foundation, давно участвовавший в судебном процессе, чтобы получить это решение.
  • Создание в АНБ должности директора по конфиденциальности и гражданским свободам. Что касается всего разведывательного сообщества США, которое включает в себя АНБ и ЦРУ, то будет запущен новый сайт, который будет включать в себя больше информации о деятельности причастных ведомств.
  • Создание независимой консультативной группы из «независимых экспертов», которая будет допущена к рассмотрению деятельности разведки и опубликует открытый доклад в течение двух месяцев и окончательный доклад в конце года. Обама не уточнил, будет ли комитет иметь полномочия как-то изменить положение вещей или будет ли правительство следовать предложениям комитета.
Как отмечает The Verge, реформы выглядят разработанными не столько для фактического изменения положения вещей, сколько для изменения общественного восприятия. В предшествовавшие месяцы Обама неоднократно выступал в защиту разведки, а недавно спецслужбы получили разрешение продолжать слежение за телефонными звонками. Американский союз гражданских свобод, являющийся давним оппонентом Обамы, назвал анонсированные рефомы необходимыми, но более чем недостаточными.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Представление чисел суммой двух квадратов и эллиптические кривые

Пусть p — нечётное простое число. Довольно широко известно, что p представимо в виде суммы двух квадратов целых чисел p=a2+b2 тогда и только тогда, когда p при делении на 4 даёт остаток 1: 5=12+22, 13=32+22, 17=12+42, ...; 3, 7, 11,… непредставимы. Куда менее известно, что a и b можно записать красивой формулой, имеющей непосредственное отношение к одной эллиптической кривой. Об этом результате 1907 года за авторством немца по фамилии Jacobsthal и о связанных вещах мы сегодня и поговорим.

Совсем легко понять, почему 3, 7, 11 и прочие числа, дающие при делении на 4 остаток 3, непредставимы в виде a2+b2: квадрат чётного числа всегда делится на 4, квадрат нечётного числа всегда даёт остаток 1 при делении на 4, сумма двух квадратов при делении на 4 может давать остатки 0, 1 или 2, но никак не 3. Представимость простых чисел вида 4k+1 неочевидна (особенно если заметить, что простота существенна: число 21 хотя и имеет нужный остаток, но суммой двух квадратов не представляется).

Вычеты
Натуральных чисел бесконечно много. Бывает полезно объединять их в классы по каким-нибудь признакам. В частности, объединение по остатку от деления на какое-нибудь число n приводит к вычетам по модулю n: вычет x? — это класс всех чисел, которые при делении на n дают тот же остаток, что и x. Что эквивалентно, вычет x? состоит из всех чисел вида x+n•k, где k целое. В рамках данного поста все вычеты будут по модулю p (того самого нечётного простого числа из введения). Естественно, различных вычетов столько же, сколько может быть остатков от деления на p, то есть ровно p. По сравнению с бесконечностью натуральных чисел переход к вычетам сильно сокращает число вариантов.
Операции над классами далеко не всегда имеют смысл. Например, попытка сложить класс простых чисел с классом составных чисел не очень осмысленна: мы умеем складывать только числа, а у суммы простого числа и составного числа не видно свойств, общих для класса. Хотя члены клуба тавтологии и могут сказать, что сложение класса простых чисел и класса составных чисел даёт класс чисел, раскладывающихся в сумму простого числа и составного числа.

Для вычетов, тем не менее, сложение, вычитание и умножение, «унаследованные» от натуральных чисел, дают другие вычеты. Например, 2?+3?=5?: возьмём любое число с остатком 2, любое число с остатком 3, и их сумма обязательно даст остаток 5. Вообще говоря, произведение двух ненулевых вычетов по произвольному модулю может внезапно оказаться нулём, 2?•3?=0? по модулю 6, что неприятно. Но в случае простого модуля, очевидно, такого не бывает, как говорят, нет делителей нуля. Кроме того, можно решить уравнение a?•x?=b? (операция деления) для любых двух вычетов, кроме случая a?=0?, и результат будет однозначно определён. Однозначность следует из того, что произведение ненулевых вычетов ненулевое. Поскольку a??0?, то наибольший общий делитель a и p равен 1 (здесь тоже нужна простота p), расширенный алгоритм Евклида найдёт x и y такие, что a•x+p•y=1, откуда следует a?•x?=1?, а значит, a?•(b?•x?)=b?.

Важное следствие из отсутствия делителей нуля: ненулевой многочлен от одной переменной степени n не может иметь более n корней. (Это хорошо известно для обычных целых чисел, но при использовании операций над вычетами требует дополнительного обоснования: уравнение 3?•x?=0? по модулю 6 имеет три решения 0?, 2?, 4?.) Действительно, обычное деление «в столбик» показывает, что любой многочлен f(x) можно представить в виде f(x)=(x-с)g(x)+(некоторая константа), где многочлен g(x) имеет степень на единицу меньше; если c — это корень f(x), то константа равна нулю (подставим x=c); если c' — другой корень f(x), то он будет корнем g(x) (здесь важно отсутствие делителей нуля), так что процесс можно продолжить. Если уже набралось n корней, то оставшийся g(x) будет константой, причём ненулевой (иначе f(x)=0) и больше корней не имеет.

Вычеты по простому модулю можно складывать, вычитать, умножать. На ненулевые вычеты можно делить. Все эти операции обладают обычными свойствами типа a?•b?=b?•a?. В умных книгах говорят, что вычеты по простому модулю образуют поле (а вычеты по составному модулю, где делить нельзя, а всё остальное такое же, — коммутативное кольцо). И не надо быть умной книгой, чтобы назвать это поле конечным. Поле вычетов — не единственное конечное поле, но другие конечные поля нам не понадобятся.

Чуть-чуть про эллиптические кривые
Эллиптическую кривую по модулю p (тому самому нечётному простому числу) можно рассматривать как набор решений уравнения y2=x3+a2x2+a4x+a6, где x, y и все a — вычеты (каждое решение называется одной точкой), плюс одна специальная точка O, не имеющая пары x, y. Правая часть уравнения не должна делиться на квадрат, иначе это будет не эллиптическая кривая: в уравнении типа y2=(x-1?)2(x+2?) можно переменную y заменить на z=y/(x-1?) и получить зависимость второй степени, а не третьей.
Если p?3, то вместо переменной x можно взять x+a2/3?, избавившись от члена с x2.

Ясно, что раз x, y принадлежат конечному множеству, то число точек на эллиптической кривой тоже конечно. Сколько их? Это сложный в общем случае вопрос. Мы ограничимся кривыми вида y2=x3-k•x. Для таких кривых полное доказательство можно уложить в один пост Хабра (хотя и довольно длинный).

Квадратичные вычеты и невычеты
Зададимся сначала более простым вопросом. Сколько решений есть у уравнения y2=c, где y, c — вычеты? Пример для p=7:
y0?1?2?3?4?5?6?
y20?1?4?2?2?4?1?
Если c=0?, то решение одно, y=0?. Остальные значения y разбиваются на две половины, от 1? до вычета, соответствующего (p-1)/2, и от вычета, соответствующего (p+1)/2, до -1?. Раз y2=(-y)2, вторая половина строки значений y2 зеркально-симметрична первой половине. С другой стороны, в каждой половине повторений нет, поскольку иначе у уравнения было бы как минимум 4 решения, что невозможно для многочлена степени 2. Значит, есть (p-1)/2 вычетов c, для которых решений ровно 2, и столько же вычетов c, для которых решений нет совсем.

Ненулевые вычеты c, для которых есть решение, называются квадратичными вычетами. Вычеты c, для которых решения нет, называются квадратичными невычетами. Стоит отметить, что квадратичный невычет — это таки вычет, просто ему не повезло быть квадратичным. Символ Лежандра \left(\frac cp\right)показывает отношение c к квадратам: 1, если относится (то есть c — квадратичный вычет), -1, если не относится (то есть c — квадратичный невычет), 0, если c=0?. Число решений уравнения y2=c равно 1+\left(\frac cp\right).

Вернёмся к эллиптическим кривым. Число вариантов y для фиксированного x мы знаем, общее число точек на кривой y2=x3-k•x можно записать, просуммировав по всем x и не забыв про специальную точку: p+1+\sum_{x\in\mathbb{F}_p}\left(\frac{x^3-kx}p\right). Символом Fp, который раньше не появлялся, принято обозначать поле (field) вычетов по модулю p.

Теперь мы готовы предъявить обещанные формулы для компонентов разложения p в сумму двух квадратов. Теорема. Пусть g — любой квадратичный невычет. Если p при делении на 4 даёт остаток 1, то
p=\left(\frac12\sum_{x\in\mathbb{F}_p}\left(\frac{x^3-x}{p}\right)\right)^2+\left(\frac12\sum_{x\in\mathbb{F}_p}\left(\frac{x^3-gx}{p}\right)\right)^2
причём число в первой скобке целое нечётное, число во второй скобке целое чётное. Если же p при делении на 4 даёт остаток 3, то обе суммы в скобках нулевые (а значит, число точек на эллиптических кривых равно p+1).

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

Часть 1. Случай p=4k+3 и вопросы чётности/нечётности.Если взять ненулевой вычет c и умножить его на все вычеты от 1? до p?-1?, все произведения будут ненулевыми и попарно различными (если c•x=c•y, то c•(x-y)=0?, что при ненулевом c может быть только если x=y), а значит, это будет просто какая-то перестановка всех вычетов от 1? до p?-1?. Следовательно, 1?•2?•...•(p?-1?)=(c•1?)•(c•2?)•...•(c•(p?-1?))=cp-1•1?•2?•...•(p?-1?) и cp-1=1? для любого ненулевого вычета c. (Это было доказательство малой теоремы Ферма.)

Значит, многочлен xp-1-1=(x(p-1)/2-1)(x(p-1)/2+1) имеет p-1 корней. Значит, каждая скобка имеет (p-1)/2 корней (максимально возможное количество для степени скобок). Каждый квадратичный вычет — корень первой скобки (если x=c2, то x(p-1)/2=cp-1=1?), их (p-1)/2, значит, всем квадратичным невычетам остаётся вторая скобка. Итак, символ Лежандра от c принадлежит тому же вычету, что и c(p-1)/2. (Это было доказательство критерия Эйлера).

Как следствие, получаем \left(\frac{cd}p\right)=\left(\frac cp\right)\left(\frac dp\right).

Является ли -1? квадратичным вычетом? Зависит от знака (-1)(p-1)/2. Если p при делении на 4 даёт остаток 1, то (p-1)/2 чётно, (-1)(p-1)/2=1, -1? — квадратичный вычет. Если p при делении на 4 даёт остаток 3, то всё наоборот и -1? — квадратичный невычет.

Простая часть теоремы: p даёт остаток 3 при делении на 4. Тогда в каждой скобке слагаемые с x и -x отличаются друг от друга умножением на символ Лежандра от -1?, то есть противоположны по знаку и в сумме дают 0. Поскольку все слагаемые, кроме x=0?, разбиваются на пары с нулевой суммой, а слагаемое с x=0?, нулевое, вся сумма равна 0.

Если p даёт остаток 1 при делении на 4, то слагаемые с x и -x равны и их сумма четна. Значит, вся сумма также четна и числа в скобках действительно целые. Чётность/нечётность после деления пополам ненамного сложнее: в первой скобке теоремы есть три нулевых слагаемых, остальные слагаемые разбиваются на (p-3)/2 пар с суммой ±2 в каждой паре; при любом знаке при делении на 4 получается остаток 2, вся сумма при делении на 4 даёт остаток такой же, как p-3, то есть 2. После деления пополам получим нечётное число. Во второй скобке теоремы всего одно нулевое слагаемое и (p-1)/2 пар с ±2, итоговый остаток от деления на 4 получается 0, после деления пополам остаётся чётное число.

Часть 2. Случай p=4k+1.Пусть p при делении на 4 даёт остаток 1. Обозначим первую скобку теоремы через a, вторую через b. Мы уже знаем, что a и b целые.

Для доказательства посчитаем двумя способами следующую странную величину N: число пятёрок вычетов (x1, y1, x2, y2, t) таких, что выполнены сразу два уравнения: y12=x13-t•x1 и y22=x23-t•x2.

В первом способе сначала зафиксируем t и посчитаем число четвёрок из x, y, после чего сложим результаты для всех t. Ясно, что при фиксированном t пара (x1, y1) может быть любой неспециальной точкой кривой y2=x3-t•x, вторая пара (x1, y1) — столь же любой неспециальной точкой той же кривой, а общее число таких пар равно квадрату числа неспециальных точек. (Собственно, поэтому мы и рассматриваем странную величину, она позволяет подобраться к a2 и b2.) Если t=0, то уравнение y2=x3, как уже говорилось, не задаёт эллиптическую кривую и имеет столько же решений, сколько уравнение z2=x (где y=z•x), то есть ровно p. При t=1 получается p+2a решений, при t=gp+2b решений. Что насчёт остальных значений t?

Если y2=x3-t•x и c — какой-то ненулевой вычет, то c6y2=c6x3-c6t•x, что эквивалентно (c3y)2=(c2x)3-c4t•(c2x). Иными словами, если (x,y) — решение уравнения с t, то (c2x,c3y) — решение уравнения с c4t, так что число решений с t и с c4t совпадает. Сколько есть разных ненулевых вычетов вида c4? С одной стороны, не менее (p-1)/4: (p-1) значений c могут «склеиваться» в группы размером не более 4. С другой стороны, если (p-1)/4 — целое число, то все такие вычеты — корни многочлена x(p-1)/4-1, так что их не может быть больше (p-1)/4. Значит, их ровно (p-1)/4.
Итак, (p-1)/4 кривых имеют p+2a неспециальных точек, ещё (p-1)/4 кривых имеют p+2b неспециальных точек. Это уже половина всего, что надо.

Если y2=x3-t•x, то g3y2=(g•x)3-(g2t)(g•x). При фиксированном x число решений уравнения g3y2=... равно 2 — число решений уравнения y2=.... Значит, число неспециальных точек на кривой с t=g2 (а следовательно, на (p-1)/4 подобных кривых) равно 2p-(p+2a)=p-2a. Аналогично число неспециальных точек на кривой с t=g3 равно 2p-(p+2b)=p-2b.

Итак, первый способ вычисления даёт
N=p^2+\frac{p-1}4\cdot(p+2a)^2+\frac{p-1}4\cdot(p+2b)^2+\frac{p-1}4\cdot(p-2a)^2+\frac{p-1}4\cdot(p-2b)^2=p^3+2(p-1)(a^2+b^2)

Во втором способе вычисления N сначала зафиксируем x1 и x2 и посчитаем число троек t и y, после чего сложим результаты для всех пар x. При x1=x2=0? есть ровно p вариантов: оба y должны быть нулями, t может быть любым. При x1=0? и ненулевом x2 должно быть y1=0, y2 может быть любым, t вычисляется однозначно, получается снова p вариантов. Ситуация с нулевым x2 и ненулевым x1 симметрична. Наконец, пусть оба x ненулевые. Тогда t=x12-(y12/x1) и нужно посчитать число пар y с условием (x2/x1)y12=y22+x2(x12-x22).

Если x1=x2, то уравнение превращается в условие совпадения квадратов y, и различных пар y получается 1+2(p-1): нулевая и по два варианта y2 для каждого ненулевого y1. Если x1=-x2, ситуация аналогичная, поскольку p даёт остаток 1 при делении на 4 и -1? — квадратичный вычет.

Если x2/x1 — квадратичный вычет, не равный ±1?, то существует какое-то ненулевое c такое, что c2=x2/x1. Тогда (c2y12-y22)=(c•y1-y2)(c•y1+y2)=x2(x12-x22), выражение c•y1-y2 может быть любым ненулевым вычетом, по нему однозначно определяется c•y1+y2 и, следовательно, y1 и y2. Итого p-1 вариантов.

Если x2/x1 — квадратичный невычет, то аналогично эллиптическим кривым число решений равно 2p минус число решений в случае квадратичного вычета, то есть 2p-(p-1)=p+1.

Суммируем. Есть один вариант с x1=x2=0, дающий p решений. Есть 2(p-1) вариантов, где один из x нулевой, а другой ненулевой, каждый из вариантов даёт p решений. Есть 2(p-1) вариантов с x2=±x1, каждый из которых даёт 2p-1 решений. Есть (p-1)((p-1)/2-2) вариантов, где x1 — произвольный ненулевой вычет, а x2/x1 — квадратичный вычет, отличный от ±1?, каждый из этих вариантов даёт p-1 решений. Наконец, остаётся (p-1)2/2 вариантов, где x1 — произвольный ненулевой вычет, а x2/x1 — квадратичный невычет, в каждом из этих вариантов p+1 решений. Итого N=p^3+2p(p-1).

Сравнение двух выражений для N завершает доказательство.


Причём здесь криптография?
Вычислять a и b, подсчитывая p раз символы Лежандра, непрактично. Куда быстрее с этим справится алгоритм Cornacchia. Практическая польза — использовать формулу для a, b в обратную сторону: можно доказать, что разложение p=a2+b2 единственно с точностью до перестановки a и b и смены знаков, так что нахождение a и b влечёт знание числа точек на кривых y2=x3-t•x для любого ненулевого t, это будет p+1±2a и p+1±2b.

Знание числа точек на кривой важно для криптографии на этой кривой. На эллиптической кривой можно ввести операцию сложения точек (о чём слышали, наверное, все, кто хоть что-то знает о криптографии) со специальной точкой O в роли нуля. На основе операции сложения можно определить умножение на натуральное число: 2P=P+P, 3P=P+P+P и так далее. Так вот, можно доказать, что если n — порядок кривой, то nP=O для любой точки P. Зная n, c, d, можно решать уравнения вида x•(cP)=dP полностью аналогично делению вычетов: расширенный алгоритм Евклида найдёт x, y такие, что c•x+n•y=1, откуда x•(cP)+y•(nP)=P, то есть x•(cP)=P. При этом, если c, d неизвестны, а cP и dP заданы координатами, то эффективных методов деления в общем случае неизвестно.

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

Если нас устраивает простое число вида 4k+1 и кривая специального вида y2=x3-t•x (в некотором смысле это одна и та же кривая при любом ненулевом t) с числом точек p+1±2a или p+1±2b, можно её и взять. Что насчёт других кривых?

Немного позднее, в 1911 году, уже другой автор von Schrutka получил аналогичный результат для кривых вида y2=x3-t, простых вида 6k+1, представления p=a2+3b2. Значит, найти число точек на кривой y2=x3-t опять же позволяет алгоритм Cornacchia.
Пара слов о доказательствеДоказательство в целом аналогично изложенному выше, только появляются три числа a, b1, b2 для t=1, g2, g4, где g не является кубом, их сумма равна нулю, а сумма квадратов вычисляется. После несложных преобразований получается то, что надо.

Позднее, по мере развития теории эллиптических кривых, выяснилось, что если есть какое-то представление 4p=a'2+d•b'2, где d натуральное, при делении на 4 даёт остаток 0 или 3, взаимно простое с p и не слишком большое, то можно эффективно (даже если p очень большое) построить кривую, которая будет иметь ровно p+1±a' точек. Два наименьших значения d=3 и d=4 соответствуют кривым y2=x3-t и y2=x3-t•x. Пример для d=163:
y^2=x^3-(2^4\cdot5\cdot23\cdot29\cdot163)x+(2\cdot7\cdot11\cdot19\cdot127\cdot163^2)
При нечётном p?163 это уравнение задаёт эллиптическую кривую. Если 4p представимо в виде a'2+163b'2 с целыми a', b', то число точек на эллиптической кривой равно p+1±a'. Если нет, то p+1. К сожалению, доказательство использует «тяжёлую» теорию, поэтому здесь не будет даже намёков.
Обычно, впрочем, будут получаться радикалы. Например, для d=15: y^2=x^3+\left(21\cdot\frac{1+\sqrt5}{2}-3\right)x-\left(28\cdot\frac{1+\sqrt5}{2}+42\right). Если 4p раскладывается в сумму a'2+d•b'2 и p взаимно просто с d, то все радикалы обязательно извлекутся (например, для d=15 обязательно найдётся вычет c, для которого c2=5? ) и получится эллиптическая кривая с нужным числом точек.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Автомат Гаусса — реальное оружие для гика (и не только)



На Хабре не раз и не два описывались разнообразные конструкции самодельных винтовок и пистолетов Гаусса. А как насчет автомата Гаусса? Причем автомат с достаточно высокой начальной скоростью вылета «пули». Обычно демонстрируются проекты с «пулями», которые еле долетают до цели, а тут серьезная убойная сила, пули протыкают даже крышку ноутбука.

Этот автомат, получивший название CG-42, имеет магазин (само собой) на 15 «патронов». Патроны, собственно, не являются патронами, это просто заостренные металлические болванки (половина гвоздя без шляпки). Полный магазин можно расстрелять за 1,5 секунды. Выглядит все это впечатляюще, как сам автомат, так и его .

Начальная скорость полета пули — немногим больше 40 метров в секунду (138 футов в секунду). Это звучит не очень серьезно, пока вы не видите работу устройства в реальности — а все это, как уже говорилось выше, впечатляет. Кроме того, «автомат Гаусса» можно удлинить, без всяких проблем, и тогда скорость полета гвоздя-пули будет еще выше.

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

А вот и демонстрация работы автомата:


А вот теоретическая информация по такому оружию, плюс инструкция по сборке: перейти.

Via Geekologie

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


MODX EVO store — первый репозиторий для MODX EVOLUTION


Приступаем к разработке

Первым шагом стало создание установщика пакетов. На это ушло пару часов, так как по факту весь код давно присутствует в в папке install, вот тут можно почитать про это.


Ну а дальше уже дело техники. После обсуждения с Bumkaka определили то, что является приоритетным и приступили к работе. Делать решили на базе MODX EVOLUTION.

И вот спустя 3 недели после возникновения идеи готовы представить вам наш небольшой стартап.


Пока функционал не очень велик и планов на доработки очень много. Но хотел бы подробней остановиться на некоторых моментах, которые выделяют наш репозиторий даже на фоне аналога для MODX REVO. Итак от слов к делу:

Ваш и только ваш личный репозиторий

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

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

После недолгих размышлений было принято решение хранить только ссылку на пакет, что дает возможность хранить пакеты где угодно, к примеру на Dropbox, Яндекс Диске, у себя на сервере или где-либо еще, открывая к ним доступ только на время пользования MODX-STORE.

Так же это дает возможность легко обновлять пакеты, как личные так и общественные, например, используя GitHub. Собственно все решения которые у нас общем репозитории уже хранятся тут: https://github.com/modx-store/
Это даст возможность всем желающим принять участие в поддержке любимых расширений, а так же всегда пользоваться свежими версиями.

Как все работает

Для начала пользованием MODX-STORE необходимо сделать всего 2 шага:

Дальнейшие планы

  • В первую очередь планируем реализовать возможность размещения платных решений в общий репозиторий.
  • А все остальные планы будем корректировать после получения отзывов от сообщества MODX и первых результатов работы репозитория.


Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Учим английский: фильмы, книги, словари

Многие из нас занимаются изучением английского языка, потому что в сфере ИТ большинство документации, форумов и просто полезной информации изложено на универсальном языке – английском. И каждый находит для себя свой подход к обучению: кто-то идет к своей цели постепенно, планомерно, кто-то более экспрессно и выборочно. В самом деле, в Интернете вы найдете более 9000 методик, о том, как эффективно и быстро выучить язык самому. В языковой школе вам предложат несколько целевых программ: от «разговорных навыков делового человека» до «целенаправленной сдачи TOEFL». Чего же нового хочу я предложить? Мы поговорим о «фоновом» изучении языка. Цель моего поста – поделиться с вами способами изучения языка, которые я использовал. Постараюсь показать концепцию в целом, который каждый из вас сможет интегрировать в свой способ познания языка.
image

Введение

Примерно 5 лет назад, когда я поступил на физический факультет, я понял: «Изучение английского языка перспективно по многим причинам». Тогда я думал о туризме, об общении с иностранцами, о необходимости языка для карьерного роста в любой сфере. Сейчас мне 22 года, я знаю английский на уровне B2-C1 (по европейской системе оценки). Я нахожу широчайшее применение языка в своей жизни: знакомство с иностранными статьями из источников, просмотр электронных лекций ведущих вузов мира, чтение научной литературы по тематике диссертации, общение с иностранцами в рамках проекта CouchSurfing, помощь желающим в изучении русского языка по скайпу и даже изучение испанского – на англоязычных сайтах.

Способы изучения языка

Я достаточно долго изучал английский, периодически, в свободное время, на занятиях в университете (3 семестра непрофильной программы), при этом я не посетил ни одного платного курса. Первым делом нужно, конечно, осознать – что вам нужен язык и что на это нужно тратить время. Я помню с чего я начал – тупо смотреть фильмы на английском с английскими субтитрами.

Просмотр фильмов на оригинальном языке
Как это правильно делать? Я совершенно тупо брал и смотрел топовые фильмы с imdb и ничего не понимал. Каждая новая фраза или длинное слово – я лез в словарь, смотрел перевод, а фильм ставил на паузу. Через 15 минут надоедает и смотришь остаток фильма как болван. Главный совет – контент, который вы хотите смотреть на английском, должен быть эффективным. Вы должны понимать основную часть произносимых слов (написанных, если смотрите субтитры), а смысл новых слов должен быть понятен из контекста или визуализирован в фильме. Выделю четыре категории, с которых можно начать:
  1. фильмы, которые вы много смотрели на русском и понимаете о чем там идет речь
  2. видеоуроки из профессиональной среды – где слова ежедневно встречаются на работе
  3. фильмы с простым языком и четким произношением (мультфильмы Disney, классика «Моя прекрасная леди», например)
  4. сериалы. Особенность сериалов в том, что обучение языку здесь происходит накопительно. Вы узнаете героев, их характерные слова и поступки, которые встречаете в дальнейшем. Хорошо прокачивается разговорный язык и уродуется ваше понимание грамматики). Рекомендую начать с сериала «Друзья». Хауса смотреть очень сложно – богатый язык сам по себе, так еще и терминология CPR, MRI и Multiple Sclerosis в каждой серии. Хотя если вы учитесь на врача – то попробуйте. Судя по названию, хабраюзерам должен понравиться сериал IT Crowd, спасибо за наводку AndreyDmitriev.
upd Q: Мне очень трудно воспринимать фильмы на английском. Это нормально, если я в начале буду мало понимать? Или мне следует повременить с просмотром на английском языке?
Нужно заставлять себя смотреть именно на английском, если ничего не понимаете, смотрите с русскими субтитрами, но на английском. Вообще, запретите себе смотреть фильмы с русской озвучкой, ищите с субтитрами. Мозг постепенно привыкает к чужому языку, нужно время для образования новых нейронных связей. Потом, в какой-то момент, вы вдруг начнёте различать иностранную речь. [Tabke]
Просмотр фильмов на английском формирует в вашем мозге языковой центр – вы учитесь различать слова, произносить их. Вы получаете больше удовольствия от оригинальной речи и шуток любимых персонажей. Сериалы мы все смотрим часто, почему бы не делать это с пользой для английского?

Погружение в английскую среду
Так как у всех, кто читает этот пост есть компьютер или, по крайней мере, браузер – то вот вам мой совет – поставьте везде английский язык интерфейса. Английская операционная система не только позволяет узнать язык – но и составить более грамотный запрос в гугле и найти ответ на вопрос на англоязычном форуме. Примерно 3 года назад я пересел на английский Windows, все операции остаются знакомыми, все ярлычки узнаются, но вы изучаете новые слова, которые встречаете вместо привычной «Корзины» или «Панели управления».

Компьютерные игры интуитивно понятны на английском, в них есть визуализация предметов. Вы сможете насладиться оригинальными видеороликами и красивыми шрифтами разработчика. Помню, с каким упоением я играл в Deus Ex: Human Revolution. И вы знаете, оригинальная атмосфера игры этому прекрасно способствует. С тех пор во все игры я играю на английском, их и скачать проще, и русифицировать не надо.Еще один абзац о том, как интересно и полезно гуглить на «буржуйском». Основная часть контента в Интернете – она на глобальном языке, причем, здесь дело не только в количестве – но и в качестве. Прочитали страницу в вики на русском – посмотрите на английском. Там запросто может быть ответ на ваш вопрос или какая-то более выразительная картинка. Прочитали перевод на хабре – поглазейте оригинал, ведь вы уже знаете о чем статья и можете запомнить несколько новых слов.

В общем и целом, принцип простой: если вы досконально освоили что-то на русском – переходите на английский и учитесь ассоциативно.

Про Интернет-ресурсы
Теперь об интерактивном обучении – о ресурсах Сети. Я достаточно много времени провел, изучая язык с помощью специальных сайтов. Многие сайты я, наверняка, не встретил, поэтому расскажу лишь о своем опыте, может, вы знаете аналоги или еще интересные проекты. (напишите сами знаете где)
  1. LinguaLeo — английский язык онлайн. Просто супер ресурс для прокачки словарного запаса. Вы смотрите популярные лекции, читаете интересные истории, слушаете любимую музыку. Как только встретили новое слово – добавляете в словарь и прогоняете его на нескольких тренировках. Можно учить слова из глоссария, но тогда теряется ассоциативный контекст, который вы можете получить, смотря лекцию или читая анекдот. Одно неудобство для студента – там разработчики хотят денег, а мне всегда было жалко, поэтому я учил по 10 слов в день, на сколько хватало фрикаделек.
  2. busuu — Learn languages for free online. Люблю этот сервис, хоть и урезанный он для бедных студентов. Здесь опять же смысл в изучении новых слов, но уроки собраны тематические. Слова из одной группы хорошо запоминаются, могут встречаться в диалогах и дополнять друг друга. А еще здесь можно найти собеседника и поговорить с ним на английском. Спросить у него скайп – и общаться уже отдельно. Сейчас на этом сервисе я изучаю испанский, при этом все объяснения идут на английском. Получается!
  3. English Grammar Exercises. Немцы состоятельно подошли к составлению тестов, их удобно решать онлайн и смотреть ответы и пояснения. По правилам можно просто нагуглить всяких сайтов – больше посоветовать не могу. Рекомендую книгу Мерфи, кстати, о книгах.

Книги по изучению языка и просто книги
Вот в этой теме я большой профан. Я практически не использовал бумажных средств для изучения. Причина простая – неудобно. Ключи к тесту нужно смотреть в конце книги, правила не интерактивные и не раскрашены в различные цвета (что облегчает восприятие).English Grammar in Use Online Raymond Murphy. Цель этого пособия – самостоятельное изучение грамматики английского языка, по тематическим упражнениям. Книга хорошо структурирована по юнитам, в каждом юните правила и замечательные упражнения.

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

В разделе про книги можно упомянуть, что основной источник изучения новых слов — это именно чтение. Чтение художественной литературы очень здорово поможет вам в изучении языка. Мы же еще в школе все читаем рассказы О'Генри и отвечаем на вопросы в конце истории. Возьмите данный подход на заметку.

upd 5 копеек от EvgeshaS:
Для себя нахожу полезным читать художественную литературу, имея под рукой русский перевод. Иногда бывает, что хотя значения всех слов знаешь, смысл фразы остается непонятным — и тогда русский перевод очень помогает. При чтении смотрю в словаре все незнакомые слова, даже когда догадываюсь об их смысле. Когда слов много, это, конечно, напрягает, но чем дальше, тем проще. Иногда полезно лишний раз заглянуть в словарь, чтобы посмотреть, как слово правильно читается. Литературу подбираю по интересам, в основном классику. Важно, чтобы интерес к книге перевешивал неудобства, связанные с необходимостью иногда подглядывать в словарь. Многократно сталкивался с тем, что непонятные мне трудные фразы и в переводе тоже отсутствуют. :)

upd Подкасты
Совершенно справедливо заметили в комментариях [goldena] про полезность подкастов – записей радиовыпусков. Они хорошо воспринимаются, как правило тематические, и замечательно научат вас языку в поездках. Я нашел для себя один очень интересный подкаст двух профессоров английского в Японии: один из Англии, другой из США. Каждый 20-минутный выпуск посвящен определенной тематике и имеет любопытные разделы. Хорошо помню раздел “Both sides of the Pond”, и особенно комичное “Ancient Japanese English Study Secret”. Слушал их с упоением, очень очень очень рекомендую. Называется просто, Bob and Rob Show. В комментариях [EvgeshaS] вам также предлагают послушать подкасты BBC, новости CNN.

Про словари
Хочется узнать значение слова – нет способа лучше, чем залезть в словарь. А в зависимости от того, какое слово вы переводите, и какой результат вы хотите получить, следует грамотно выбирать словарь. Я для вас обозначу те, которыми пользуюсь.
  1. ABBYY Lingvo. Очень функциональный словарь, который помогает не просто узнать перевода слова, но и посмотреть обороты и фразы с этим словом, идиомы. Идеальный инструмент для нахождения красивых оборотов, которые разнообразят ваше англоязычное эссе. Посмотрев пару контекстуальных примеров – слово очень легко запоминается. Лингво есть и в виде программы для ПК, рекомендую в качестве оффлайн словаря. А еще на сайте лингво периодически публикуются интересные новости об этимологии фраз и оборотов, вроде “to take a rain ticket”. Да, этот словарь еще и уникален тем, что в него можно понапихать различных тематических словарей, для различных языков. Лично мне хватает стандартного комплекта.
  2. Мультитран. Открыл для себя примерно год назад, когда попал в среду переводчиков. Сервис умеет ловко переводить целые обороты, отлично справляется с технической и научной литературой. Также как и в лингво, много оборотов и тонкостей применения. Множество языков, точно знаю, что немецкие переводчики его обожают.
  3. Dictionary. Это огромный толковый словарь английского языка. Если вы нигде не нашли подходящего перевода – то вам в этот словарь. Очень подробный, с примерами, синонимами и антонимами, единственный минус – трактовка на английском, привыкайте.
  4. UrbanDictionary. Специфический словарь, в который стоит заглянуть, если вас интересует значение сленга, ругательств или ярких непонятных выражений (цитата из сериала, например). Вы неизбежно встретитесь с такими словами, просматривая сериалы (в разговорной речи). Замечательность этого сервиса в том, что его создают сами пользователи, перевод отсеивается по количеству пальцев вверх (thumbs up, +1). А вы сходите и посмотрите, там сегодня какие-нибудь интересные words of the day!
  5. GoogleTranslate. Если нужно качественно оценить смысл какого-то параграфа – то лучше места не найти. Кроме того, этот быстрый перевод можно использовать в качестве чернового, переводя предложение за предложением вручную (при этом заменять гугловский вариант).
  6. Плагины для браузера. Когда вы начнете много читать на английском вы будете регулярно встречать новые слова, лезть в словарь из-за которых не очень хочется, и так все понятно. Тем не менее, если двойным кликом можно быстро посмотреть значение слова – то почему бы и нет. В хроме есть расширение для этого – Google dictionary. Его функционал шире, но у меня стоит именно из-за двойного клика. Подобная фича есть у десктопных приложений ABBYY Lingvo, и, наверное, еще где-то. Решите для себя эту проблему.
  7. Комментарий от EvgeshaS. Есть такой полезный список — Barron's GRE wordlist, содержащий чуть менее 5000 слов (есть сокращенная версия из 1500 слов, но она не так интересна). Почти любое встречающееся неизвестное мне слово есть в этом списке. Вывод очевиден. Конечно, учить слова по списку — не очень эффективно, но не могу сказать, что совершенно бесполезно. Для себя сделал распечатку списка — и в транспорте просто иду по всем неизвестным словам с Lingvo, смотря перевод и примеры употребления. Все слова, ясное дело, я не запоминаю, но что-то в голове откладывается. Гоняю этот список кругами.

Учимся говорить
В самом деле научиться разговору можно начать с переписки в IM, скайпе, чатах, форумах. Вы начнете формировать языковые конструкции, что-то отложится в голове, потом в разговоре будет всплывать. При переписке вас есть достаточно времени чтобы обдумать фразу, а вот лезть в словарь не хочется (задерживаете собеседника) – вы будете искать замену вашему слову, говорить описательно. это, на мой взгляд, тоже полезно.Начинайте генерировать свои мысли на английском: запоминайте обороты, конструкции предложений, типичные фразы. Я начинал писать свои перлы просто в качестве статусов в фб, твиттере. (вконтакте выглядит дико, друзья могут не понять). Напишите себе рекомендации на английском, сделайте английское резюме, научитесь представлять себя и говорить о ваших хобби. Вы хорошо это знаете на родном языке, будет проще адаптировать на другой.

Друзья по переписке – ваши помощники. Им тоже хочется выучить язык, общаться на английском и делиться впечатлениями. Таких людей можно найти на сервисах изучения языка, например, busuu. Пожалуй, отмечу, что научиться говорить и произносить красивые осмысленные и законченные фразы – непосильная задача для «фонового» обучения. Либо ищите единомышленников и собирайтесь в группах для разговора, либо много путешествуйте, либо запишитесь в волонтеры-переводчики на Сочи 2014, как это сделал я.

Заключение

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

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Петиция против антипиратского закона набрала 100 тысяч голосов!


Петиция об отмене «антипиратского» закона набрала необходимые 100 тысяч подписей на сайте «Российская общественная инициатива».
Ура, товарищи!

Сегодня, в субботу 10 августа 2013 года, инициативу против «антипиратского» закона сняли с голосования на РОИ после достижения 100057 голосов — и отправили на рассмотрение в экспертную группу.

Теперь, по закону, документ о «запрете произвольных блокировок сайтов» предстоит проанализировать специальной экспертной группе федерального уровня под руководством министра по связям с открытым правительством Михаила Абызова.
По результатам рассмотрения инициативы экспертная рабочая группа не более чем за два месяца должна подготовить заключение и решение о разработке соответствующего нормативного правового акта или принятии иных мер по реализации инициативы.

Петиция, призывающая к отмене закона о защите интеллектуальных прав в интернете, была размещена Пиратской партией России совместно с Ассоциацией пользователей интернета и проектом «Роскомсвобода» 4 июля 2013 года.
Инициатива преодолела 100-тысячный порог за месяц и одну неделю.

Новость об этом событии попалав ТОП Яндекс.Новостей и вообще распространяется по рунету лавинообразно, невзирая на выходные. Такое впечатление, что весь интернет празднует свою небольшую победу IRL. Перерастёт ли это в большую победу, сказать сложно. Но в любом случае, как написал Temych, это показало, что
Мы с вами гражданское общество, мы это доказываем нашим инструментом взаимодействия, его имя — Интернет.

Спасибо всем неравнодушным, кто так или иначе принял участие в поддержке этой инициативы.

Историческая справка
Проект «Российская общественная инициатива» запустился в апреле 2013 года. Владимир Путин в своей предвыборной статье в феврале 2012 года писал, что инициативы граждан, собравшие более 100 тысяч подписей в интернете, должны быть рассмотрены парламентом.

Предложение отменить антипиратский закон стало вторым, собравшим 100 тысяч голосов на сайте РОИ. Первой была инициатива Алексея Навального о запрете чиновникам покупать автомобили дороже полутора миллионов рублей.

UPD
Здесь можно прочесть Открытое письмо для РОИ и ФИД по петиции об отмене 187-ФЗ.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Вышел Vim 7.4

Спустя 3 года и более тысячи патчей, состоялся релиз одного из самых популярных текстовых редакторов Vim.


Из основных улучшений:
  • Улучшена поддержка Python
  • Движок regexp стал быстрее
  • Улучшена подсветка и форматирование кода Javascript и XML
  • Возможность сохранения выбранных областей в системный буфер обмена
  • Поддержка использования системного буфера обмена в качестве регистра по умолчанию
  • Реализовано автодополнение при вводе аргументов команды
    :language
  • Для разработки расширений на Lua добавлена поддержка привязки данных к структурам Vim
Также исправлено множество ошибок и внесены мелкие улучшения.

Полный список улучшений:
:help version7.4

Ссылки для загрузки:
MS-Windows: gvim
Unix: Mercurial + sources
Mac: MacVim

Помочь проекту: vim.org/sponsor

:wq


Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Звездное небо на dbCartajs

Почему

В этой статье я хочу более подробно рассказать о примере Starry Sky (Звездное Небо), реализованном с помощью скриптов dbCartajs (о них написано в предыдущей статье). Он включает в себя идеи других «звездных» проектов, которые были портированы на JavaScript. Рассмотрим их подробнее. Алгоритм формирования звездного неба был позаимствован из проекта Marble KDE плагин stars), расчет положения планет построен на основе замечательной статьи шведского астронома Поля Шлетера, модель движения космических аппаратов SGP4/SDP4 предоставлена модулем satellite-js (проект в github), формулы солнечного терминатора (ночной зоны) взяты с астрономического форума. Вид орбит как эллипсов подсмотрен у Сelestia.
Starry Sky

Демо Starry Sky имеет чисто технологическое назначение: вывести в заданное время точку положения космического аппарата при заданных орбитальных параметрах. В Canvas это получилось относительно просто и красиво и я решил подробнее написать об этом. Если нужно что-то поменять в выводе объектов, настройках не нужно перекомпилировать программу как Marble или Xephem (и соответственно устанавливать компилятор или среду разработки), достаточно иметь лишь браузер. В Mozilla или Chrome уже есть встроенные панели отладки, где можно посмотреть, скажем, массив точек траектории аппарата. Это гораздо удобнее чем «вытаскивать» их из C-й.

Почему демо? Потому что не учитываются размеры планет, собственное движение звезд, соответствие размера неба и размера Земли. Нужно добавлять соответствующие формулы. Зато учитывается положение звезд, планет и радиус космических аппаратов относительно Земли. Также вид Земли меняется вместе с изменением высоты над поверхностью (благодаря проекции nsper).

Управление

Вращение Земли происходит по клику в любой точке глобуса. В демо предусмотрен авторежим с ускорением времени (1 сек~15 минут, кнопка play рядом с датой). Анимацию с суточным периодом можно посмотреть здесь.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Перевод] Абсолютное горизонтальное и вертикальное центрирование

Сколько уже было сломано копий о задачу выравнивания элементов на странице. Предлагаю вашему вниманию перевод отличной статьи с решением этой проблемы от Стефана Шоу (Stephen Shaw) для Smashing Magazine — Absolute Horizontal And Vertical Centering In CSS.

Все мы знали о margin: 0 auto; для горизонтального центрирования, но margin: auto; не работало для вертикального. Это можно легко исправить, просто задав высоту и применив следующие стили:

<code class="css">.Absolute-Center {
  margin: auto;
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}
</code>
Я не первый, кто предложил это решение, однако такой подход редко применяется при вертикальном выравнивании. В комментариях к статье How to Center Anything With CSS Simon ссылается на пример jsFiddle, где приводится отличное решение для вертикального центрирования. Вот еще несколько источников на эту тему.

Рассмотрим способ поближе.

Достоинства

  • Кроссбраузерность (включая IE 8-10)
  • Никакой дополнительной разметки, минимум стилей
  • Адаптивность
  • Независимость от padding (без box-sizing!)
  • Работает для изображений

Недостатки

  • Должна быть задана высота (см. Variable Height)
  • Рекомендуется задать overflow: auto, чтобы контент не расползался
  • Не работает на Windows Phone

Совместимость с браузерами

Метод был протестирован, и прекрасно работает в Chrome, Firefox, Safari, Mobile Safari и даже IE 8-10. Один пользователь упоминал, что контент не выравнивается по вертикали на Windows Phone.

Внутри контейнера

Контент, размещенный в контейнер с position: relative будет прекрасно выравниваться:

<code class="css">.Absolute-Center {
  width: 50%;
  height: 50%;
  overflow: auto;
  margin: auto;
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}
</code>


С использованием viewport

Установим для контента position: fixed и зададим z-index:

<code class="css">.Absolute-Center.is-Fixed {
  width: 50%;
  height: 50%;
  overflow: auto;
  margin: auto;
  position: fixed;
  top: 0; left: 0; bottom: 0; right: 0;
  z-index: 999;
}
</code>
Смотреть демонстрацию

Адаптивность

Главное преимущество описываемого способа — это прекрасная , когда высота или ширина задана в процентах, да еще и понимание min-width/max-width и min-height/max-height.

<code class="css">.Absolute-Center.is-Responsive {
  width: 60%; 
  height: 60%;
  min-width: 400px;
  max-width: 500px;
  padding: 40px;
  overflow: auto;
  margin: auto;
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}
</code>


Смещения

Если на сайте присутствует фиксированная шапка или требуется сделать какой-то другой отступ, просто нужно добавить в стили код вроде top: 70px; Пока задан margin: auto; блок с контентом будет корректно центрироваться по высоте.

Еще можно выравнивать контент по нужной стороне, оставляя центрирование по высоте. Для этого нужно использовать right: 0; left: auto; для выравнивания справа или left: 0; right: auto; для выравнивания слева.

<code class="css">.Absolute-Center.is-Right {
  width: 50%;
  height: 50%;
  margin: auto;
  overflow: auto;
  position: absolute;
  top: 0; left: auto; bottom: 0; right: 20px;
  text-align: right;
}
</code>


Много контента

Для того, чтобы большое количество контента не позволяло верстке разъезжаться, используем overflow: auto. Появится вертикальная прокрутка. Также можно добавить max-height: 100%; если у контента нет дополнительных отступов.
<code class="css">.Absolute-Center.is-Overflow {
  width: 50%;
  height: 300px;
  max-height: 100%;
  margin: auto;
  overflow: auto;
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}
</code>


Изображения

Способ отлично работает и для изображений! Добавим стиль height: auto; тогда картинка будет масштабироваться вместе с контейнером.

<code class="css">.Absolute-Center.is-Image {
  width: 50%;
  height: auto;
  margin: auto;
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}
</code>


Изменяемая высота

Описываемый способ требует заданной высоты блока, которая может быть указана в процентах и контролироваться с помощью max-height, что делает метод идеальным для адаптивных сайтов. Один из способов не задавать высоту — использование display: table. При этом блок контента центрируется независимо от размера.

Могут возникнуть проблемы с кроссбраузерностью, возможно следует использовать способ с table-cell (описан ниже).

  • Firefox/IE8: использование display: table выравнивает блок вертикально по верхней границе документа.
  • IE9/10: использование display: table выравнивает блок по левому верхнему углу страницы.
  • Mobile Safari: если ширина задана в процентах, страдает горизонтальное центрирование
<code class="css">.Absolute-Center.is-Variable {
  display: table;
  width: 50%;
  overflow: auto;
  margin: auto;
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}
</code>


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

Отрицательный margin

Наверное, самый популярный способ. Подходит, если известны размеры блока.

<code class="css">.is-Negative {
        width: 300px;
        height: 200px;
        padding: 20px;
        position: absolute;
        top: 50%; left: 50%;
        margin-left: -170px; /* (width + padding)/2 */
        margin-top: -120px; /* (height + padding)/2 */
}
</code>
Преимущества:

  • Кроссбраузерность
  • Минимальный код
Недостатки:

  • Не адаптивный
  • Ползет верстка, если в контейнере слишком много контента
  • Приходится компенсировать отступы или использовать box-sizing: border-box

Использование transform

Один из самых простых способов, поддерживает изменение высоты. Есть подробная статья на эту тему — "Centering Percentage Width/Height Elements" от CSS-Tricks.

<code class="css">.is-Transformed { 
	width: 50%;
	margin: auto;
	position: absolute;
	top: 50%; left: 50%;
	-webkit-transform: translate(-50%,-50%);
    -ms-transform: translate(-50%,-50%);
        transform: translate(-50%,-50%);
}
</code>
Преимущества:

  • Изменяемая высота
  • Минимальный код
Недостатки:

  • Не работает в IE 8
  • Использование префиксов
  • Может мешать работе других эффектов с transform
  • В некоторых случаях при рендеринге размываются края блока и текст

Table-cell

Возможно один из самых лучших и простых способов. Подробно описан в статье "Flexible height vertical centering with CSS, beyond IE7" от 456bereastreet. Главный недостаток — дополнительная разметка: требуется аж три элемента:

<code class="html"><div class="Pos-Container is-Table">
  <div class="Table-Cell">
    <div class="Center-Block">
    <!-- CONTENT -->
    </div>
  </div>
</div>
</code>
CSS:
<code class="css">.Pos-Container.is-Table { display: table; }
.is-Table .Table-Cell {
  display: table-cell;
  vertical-align: middle;
}
.is-Table .Center-Block {
  width: 50%;
  margin: 0 auto;
}
</code>
Преимущества:

  • Изменяемая высота
  • Верстка не едет при большом количестве текста в блоке
  • Кроссбраузерность
Недостатки:

  • Сложная структура

Flexbox

Будущее CSS, flexbox будет решать множество сегодняшних проблем верстки. Подробно об этом написано в статье Smashing Magazine, которая называется Centering Elements with Flexbox.

<code class="css">.Pos-Container.is-Flexbox {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-align: center;
     -moz-box-align: center;
     -ms-flex-align: center;
  -webkit-align-items: center;
          align-items: center;
  -webkit-box-pack: center;
     -moz-box-pack: center;
     -ms-flex-pack: center;
  -webkit-justify-content: center;
          justify-content: center;
}
</code>
Преимущества:

  • Контаент может быть любой высоты или ширины
  • Может использоваться в более сложных случаях
Недостатки:


Итог

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

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Раздача интернета с 3G модема в локальную сеть в Linux

Эта статья — продолжение статьи Беспроводная точка доступа, используя Linux. Тут я опишу, что же необходимо сделать для того, чтобы раздавать интернет с 3G-модема по уже созданной по инструкции из предыдущего топика вайфай-сети.

1) Прежде всего, научить Linux работать с модемом
2) Создать NAT для раздачи интернета
3) Запихнуть всё это дело в автозагрузку
Итак, bash, wvdial и iptables под мышку — и поехали!

Подключение USB 3G-модема

Бывает и так, что в некоторых странах есть свои провайдеры 3G-интернета, которые не предоставляют настроек для подключения, используя Linux, что, в общем-то, и понятно — 'популярность' как провайдера, так и Linux даёт о себе знать. Не все конфиги есть ещё на сайтах, тем более — для отдельных программ. Итак, в Латвии, где я и проживаю. есть два провайдера — LMT и Bite. Оба они предоставляют беспроводной интернет через модемы Huawei, залоченные, естественно, на них, ну да не в этом дело. Ну так вот — необходимо обеспечить интернет всюду, где есть 3G, используя модем и сервер. Что же делать?

Прежде всего, воткнуть модем в ноут. USB-модемы определяются в Linux как устройства под адресом /dev/ttyUSB*, где * — порядковый номер устройства, обычно адрес выглядит как /dev/ttyUSB0.
<code class="bash">root@localhost:/# ls /dev/ttyUSB* 
ls: cannot access /dev/ttyUSB*: No such file or directory</code>
Ой. Что-то он не определяется. А проблема вот такая (обмусоленная уже тысячу раз): модем — это устройство типа “два в одном”. Почему? Он совмещает в одной флешке как собственно модем, так и встроенный накопитель с драйверами модема под Windows (я уже молчу про кардридер). В Linux по умолчанию включается режим диска, а не модема Для того, чтобы включить ещё и режим модема, нужно установить пакет usb-modeswitch. После этого нужно перезагрузить udev (service udev restart) и опять подключить модем, подождать секунд 10 и опять выполнить команду на вывод списка устройств модема:
<code class="bash">root@localhost:/# ls /dev/ttyUSB* 
/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 </code>
Когда вывод походит на этот, всё отлично и можно двигаться дальше. У нас есть три устройства. Нам необходимо лишь одно — под номером 0, остальные 2 мы не используем — они не для наших целей. Насколько мне известно, одно из них, скорее всего, используется для отсылки СМС, а второе — для просмотра уровня сигнала сети и прочего.

Теперь — дело за программой, которая подключит нас. Я буду использовать программу wvdial, дополнительно к ней нужно установить пакет ppp, если он ещё не установлен.
<code class="bash">apt-get install ppp wvdial</code>
Многие советуют использовать программу wvdialconf для настройки подключения, но в данном случае она нам не поможет. После установки нам нужно отредактировать файл /etc/wvdial.conf. Стираем из него всё содержание, затем разбираемся в формате файла. Я предоставлю рабочие конфиги для провайдера LMT с тарифом OKarte Internets datora и модемом Huawei E173 и Bite с неизвестным тарифом и модемом Huawei E1550.

<code class="bash">[Dialer lmt] 
Init1 = AT
Init2 = AT&FE0V1X1&D2&C1S0=0
#Init3 = AT+CPIN="1219" 
Init4 = AT+CGDCONT=1,"IP","internet.lmt.lv" 
Phone = *99# 
ISDN = 0
Username = { } 
Password = { } 
Ask Password = 0 
Modem = /dev/ttyUSB0 
PPPD Options = noauth crtcts multilink usepeerdns lock defaultroute nobsdcomp nodeflate refuse-pap refuse-eap refuse-chap refuse-mschap +chap 
Idle Seconds = 3000 
Modem Type = USB Modem 
Compuserve = 0 
Auto DNS = 1 
Dial Command = ATD 
Stupid Mode = 1 
FlowControl = NOFLOW
[Dialer bite] 
Init1 = AT
Init2 = AT&FE0V1X1&D2&C1S0=0
#Init3 = AT+CPIN="1219"
Init4 = AT+CGDCONT=1,"IP","internet" 
Phone = *99# 
ISDN = 0 
Username = { } 
Password = { } 
Ask Password = 0 
Modem = /dev/ttyUSB0 
PPPD Options = noauth crtcts multilink usepeerdns lock defaultroute nobsdcomp nodeflate refuse-pap refuse-eap refuse-chap refuse-mschap +chap 
Idle Seconds = 3000 
Modem Type = USB Modem
Compuserve = 0 
Auto DNS = 1 
Dial Command = ATD 
Stupid Mode = 1 
FlowControl = NOFLOW</code>

Вкратце — файл разделён на секции. Каждая из секций отвечает за одну комбинацию модем-провайдер. Начало секции обозначается меткой [Dialer xxx], где ххх — это название метки, по которой мы будем указывать, какие именно настройки нужны для подключения. Если нам потребуются настройки LMT, мы наберём команду wvdial lmt, и будут использоваться настройки из секции [Dialer lmt] — суть понятна. Из этих настроек нам нужно обратить внимание на следующие:

<code class="bash">InitX = AT-BLABLABLA</code>
— AT-команды после InitX — те команды, которые wvdial отсылает модему перед тем, как поднять подключение.

<code class="bash">#Init3 = AT+CPIN="1219"</code>
— Эта настройка, если убрать # в начале, будет посылать модему команду ввода пин-кода. Если честно, желательно её отключить — у меня эта команда по непонятным причинам не работала корректно. Легче просто подключить модем один раз к компьютеру с Windows и отключить ввод пин-кода при подключении, используя программу, поставляемую с модемом.

<code class="bash">Init4 = AT+CGDCONT=1,"IP","internet" </code>
— Здесь прописывается адрес APN, который предоставляет провайдер. Нужно обратить внимание на две последних отделённых кавычками части. Первая — IP — указывает IP-адрес для подключения, если настройки провайдера подразумевают то, что используется IP-адрес APN. Если же используется буквенный адрес вида “internet” или “internet.lmt.lv”, в первой части нужно оставить “IP”, а во второй — прописать буквенный адрес, как это сделано в примере.

<code class="bash">Phone = *99# </code>
— Ну тут всё стандартно — этот номер телефона используют практически все провайдеры, и менять его в большинстве случаев не понадобится.

<code class="bash">Username = { } 
Password = { } </code>
Имя пользователя и пароль для подключения к интернету. Если их нужно оставить пустыми, оставьте там скобочки вида { }. Если нет — просто поставьте там имя и пароль, без скобочек.

<code class="bash">Modem = /dev/ttyUSB0</code>
Имя устройства, которое нам нужно использовать. В 99% случаев оно будет именно таким.

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

Ещё раз расскажу о том, как правильно запускать подключение вручную. Достаточно одной команды — wvdial xxx, где ххх — это название провайдера из конфигурационного файла (для меня это либо lmt, либо bite.) Однако — при запуске wvdial ”занимает собой” всю консоль, не давая возможности запустить что-либо ещё. Кроме того — если вы запустите wvdial в окне SSH и тут же разорвёте сессию, то и wvdial завершится. Нужно либо постоянно держать сессию открытой, либо использовать screen, который в данном случае решает сразу две проблемы довольно эффективно — что и советую.
Что в идеале нужно? Также научиться просто и легко запускать эти программы. В использовании мной описанной схемы есть свои нюансы:

1) Соединение нужно каждый раз запускать вручную.
— Достаточно немного изменить конфигурационные файлы системы, а именно — тот же /etc/network/interfaces:
<code class="bash">auto ppp0 
iface ppp0 inet wvdial 
provider lmt
#Поднимать интерфейс ppp0 автоматически
#Для подключения вызывать команду wvdial с аргументом lmt. Естественно, аргумент будет меняться.
</code>
Для меня этот способ не подходит — он рассчитан на то, что провайдер не меняется, но большая вероятность, что это понадобится кому-то ещё. Да и не особо-то надёжно это работает, по моему опыту, лучше настроить udev. Для себя же я не нашёл подходящих решений — для этого надо было бы определять принадлежность вставленной сим-карты тому или иному провайдеру, а решение с использованием этого становится очень сложным.
Ну а если всё же надо быть постоянно подключённым, даже если что-то глючит и модем отключается от сети? Ну тогда поможет следующий скрипт. Он смотрит, есть ли wvdial в списке процессов, а если нет, то делает ifup ppp0, что в совокупности с вышеупомянутыми настройками в interfaces должно вызывать wvdial заново:
Засунуть себе в cron
<code class="bash">#!/bin/bash
# ©2009 John de Graaff, rewritten by CRImier
# This script checks if wvdial is running.
# If it's not, it brings ppp0 up and down.
# It is assumed that ifup ppp0 starts wvdial
if test "$(pidof wvdial)" != "" ; 
then
	exit 0
else
	logger "wvdial not running. Better restart ppp0."
	/sbin/ifdown ppp0
	sleep 2
	/sbin/ifup ppp0
	logger "ppp0 restarted."
	exit 0</code>


2) При включении ноутбука, если модем был подключен во время загрузки системы, иной раз случаются зависания, которые выражаются в следующем — при попытке подключения, используя wvdial, выходят строчки вида
<code class="bash">--> Cannot open /dev/ttyUSB0: Device or resource busy </code>
, и подключиться не удаётся. Лечится на один раз просто — нужно лишь вынуть и воткнуть модем, а затем запустить соединение вручную, но вы же понимаете, что при отсутствии физического доступа к компьютеру эта задача усложняется до невозможности.
— Пока что я не могу предоставить нормального решения, поскольку сам ещё не занялся этим. Предполагают, что это из-за того, что программа usb-modeswitch не отрабатывает корректно, если модем вставлен в компьютер при запуске системы. Видимо, нужно покопаться с udev или указать какие-либо особые параметры для usb-modeswitch.

3) В условиях плохого приёма соединение часто обрубается
— Всё довольно просто. Дело в том, что у портов ЮСБ есть ограничение на отдаваемый ток, при превышении которого, насколько я помню, порт отрубается. Видимо, в условиях плохого приёма сигнала сети модем пытается повысить мощность приёмника и передатчика, и случается так, что модем начинает потреблять больший ток, чем выдерживает порт — порт отключается, модем выключается, соединение отрубается насовсем. Посоветовать могу лишь, к примеру, просто-напросто взять USB-хаб с внешним питанием ну или же купить отдельный адаптер питания для модема и впаять его в кабель.

4) Возможность смены порта, по которому нужно обращаться к устройству.
Как я уже упомянул, обычно при настройке используется одно устройство — /dev/ttyUSB0. Но, как заметил freuser, есть ситуации, когда порт меняется. К примеру:
  • Использование двух модемов
  • Зависание одного порта, которое выражается в том, что порт остаётся в /dev, даже если модем уже отключен...
  • И тому подобные казусы, при которых внезапно назначается другой порт.
При дебаге неработающего подключения нельзя забыть про такую возможность. Если, к примеру. при запуске wvdial не стартует pppd, то это повод задуматься — а работает ли сам порт и тот ли это порт? Тогда придётся поэкспериментировать с номерами в конфиге, пока модем наконец не подключится.

После того, как интернет появился на нашем сервере, остаётся лишь настроить раздачу интернета с модема по Wi-Fi сети.

NAT

Если у компьютера есть два сетевых интерфейса, это ещё не означает, что из коробки можно спокойно раздавать интернет с одного на другой. Однако — не всё так сложно, чаще всего требуется всего пара настроек. Конечно, эти настройки сложно запомнить, не вникая в суть каждой строчки, но ведь для этого есть эта статья! Я нашёл наиболее подходящий для этой ситуации и безглючный скрипт, не могу не дать ссылку на него, поскольку найденный на нём скрипт самый короткий и ясный из тех, что я встречал — остальные умудряются растянуть пару правил iptables на несколько страниц… Прежде всего, посмотрю, что в нём надо бы изменить под мои нужды:

Найденный скрипт
Спойлер:
<code class="bash">#!/bin/sh

PATH=/usr/sbin:/sbin:/bin:/usr/bin

#
# delete all existing rules.
#
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X

# Always accept loopback traffic
iptables -A INPUT -i lo -j ACCEPT


# Allow established connections, and those not coming from the outside
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state NEW -i ! eth1 -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow outgoing connections from the LAN side.
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT

# Masquerade.
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

# Don't forward from the outside to the inside.
iptables -A FORWARD -i eth1 -o eth1 -j REJECT

# Enable routing.
echo 1 > /proc/sys/net/ipv4/ip_forward</code>

Хм-хм. Этот скрипт уже староват — iptables ругается на одну из команд и не хочет выполнять, да и тот путь, которым в статье скрипт пытаются поместить в автозагрузку, тоже работает не всегда на моей практике. Более того, есть проблема — этот скрипт отлично подходит для ситуации, когда ничего не собирается меняться. Если бы так и было, я бы поставил iptables-persistent и на этом закончил бы статью. А вот я собираюсь иногда получать интернет по интерфейсу ppp0, иногда — по eth0, а иногда — вообще по wlan1, причём менять интерфейс хочу одной консольной командой. Так, eth1 в примере — внешний интерфейс, а eth0 — внутренний. Заменим их переменными, чтобы при необходимости можно было поменять одну строчку, а не редактировать весь текст. Также я хочу, чтобы при перезапуске компьютера последний выбранный внешний интерфейс сохранялся. Что тогда? Нужно всё поменять!
Задачи:
  1. Принимать первый аргумент командной строки в качестве названия внешнего интерфейса, проверяя подлинность имени, используя команду ifconfig;
  2. Добавить сохранение выбранного интерфейса в какой-нибудь файл в /etc и сделать ключ выбора последнего интерфейса, а лучше — при отсутствии имени интерфейса как аргумента.
  3. Запихнуть это всё красиво в автозагрузку и в $PATH.
Что же вышло в итоге?
<code class="bash">#!/bin/bash
#NAT script from www.debian-administration.org, modified by CRImier
# Exit status 0 if operation is correct
# Exit status 1 if trying to use last interface used when running for the first time
# Exit status 2 if interface doesn't exist
EIF=''
IIF='wlan0'
PATH=/usr/sbin:/sbin:/bin:/usr/bin
LOGFILE=/etc/nat-if.conf
touch $LOGFILE

#
#Checking command-line arguments and setting $EIF variable according to them
#

if [[ $1 == "" ]] #If there's no arguments, just use previous settings.
then
	EIF=`cat $LOGFILE`
	if [[ $EIF == "" ]] #Just check for an empty file!
	then
		echo "Please, specify interface name for first usage using 'firewall interface', e.g. 'firewall eth0'"
		exit 1
	fi
elif [ $1 == "help" ] #Output help message
then
	echo "NAT script"
	echo "© www.debian-administration.org, modified by CRImier"
	echo "Usage: 'firewall interface', 'firewall info' or simply 'firewall' to use last interface firewall was set on."
	echo "Argument is external interface name, internal interface name is hard-coded in the script"
	exit 0
elif [ $1 == "info" ] #Print interface firewall is set on
then 
	cat $LOGFILE
	exit 0
else
	ifconfig $1 &>/dev/null
	if [ $? == 0 ]
	then #Interface name must be correct as ifconfig gives 0 exit code
		EIF=$1
		echo $EIF > $LOGFILE 
	else 
		echo "Incorrect interface name"
		exit 2
	fi
fi

#
#$EIF is set correctly, let's apply the rules:
#

iptables -F 
iptables -t nat -F
iptables -t mangle -F
iptables -X
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i $EIF -o $IIF -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i $IIF -o $EIF -j ACCEPT
iptables -t nat -A POSTROUTING -o $EIF -j MASQUERADE
iptables -A FORWARD -i $EIF -o $IIF -j REJECT
echo 1 > /proc/sys/net/ipv4/ip_forward
echo "Firewall started."</code>
Комментарии писал на английском — так привычнее. Если будут просьбы — могу и перевести.
Ну и не забываем обязательную часть:
<code class="bash">chmod +x /etc/init.d/user-autorun</code>
Окей, скрипт у нас готов. Как можно понять, вариантов вызова четыре — firewall (используется последний интерфейс), firewall наш_интерфейс, firewall info (выводит текущий интерфейс, на котором настроен NAT) или firewall help. Осталась лишь автозагрузка и $PATH.

<code class="bash">echo $PATH 
>/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin</code>
Для того, чтобы вызывать скрипт командой firewall, не указывая местоположение, нужно запихнуть его в одну из папок, указанных в PATH. Я предпочитаю /usr/local/bin по религиозным соображениям. Полный путь к скрипту будет /usr/local/bin/firewall, а вот вызвать из консоли его всегда можно будет просто командой firewall.

Автозагрузка

А теперь — автозагрузка, с ней посложнее. Я сразу опишу создание скрипта автозагрузки, в который можно будет запихнуть всё, что угодно. Он будет стартовать вместе с системой, нооо…

Нельзя просто так взять и создать файл автозагрузки. Есть одна проблема — Debian с какого-то времени пересмотрел свои требования к файлам автозагрузки. Файл мало просто создать, его нужно ещё по-особому отформатировать:
  1. Первая проблема — это LSB headers. Это заголовок файла автозагрузки. Нужен он потому, что компоненты автозагрузки должны выполняться в определённом порядке, поскольку часть из них зависят друг от друга. Предположим, у вас есть два скрипта в автозагрузке — один из них должен будет монтировать сетевую папку, а второй — делать в неё резервную копию файлов. Естественно, что сначала нужно выполнить первый, а потом — второй, поскольку второй зависит от первого. Для указания таких зависимостей и используются заголовки загрузочного файла. Впрочем, будет достаточно того заголовка, который я выложу в образце файла автозагрузки.
  2. Вторая проблема — любой скрипт в автозагрузке при запуске системы вызывается командой /etc/init.d/script start, а при выключении компьютера — командой /etc/init.d/script stop. Нужно добавить условия для обработки этих случаев.
Я сделал просто — взял за основу скрипт из имеющихся в /etc/init.d/ — уж они-то должны быть созданы по правилам, потом изучил этот скрипт и вырезал из него всё ненужное. Осталось два места, которые нужно изменить — место для команд, которые выполняются при запуске системы, и место для команд, которые выполняются при выключении компьютера. Впрочем, сейчас всё увидите:

<code class="bash">#!/bin/sh

### BEGIN INIT INFO
# Provides:          firewall
# Required-Start:    $network $local_fs $remote_fs
# Required-Stop:     $network $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# X-Interactive:     false
# Short-Description: Start user autorun events
### END INIT INFO

case "$1" in
	start)
		echo "Starting user autorun events"
		/usr/local/bin/firewall 
		#Место для команд, которые должны выполниться при запуске системы
		;;
	stop)
		echo "Stopping user autorun events"
		#Место для команд, которые должны выполниться при завершении работы системы
		#Останавливать NAT нет необходимости
		;;
	*)
		echo "Usage: /etc/init.d/user-autorun {start|stop}"
		exit 1
		;;
esac

exit 0</code>
Опять же, дать права на исполнение:
<code class="bash">chmod +x /etc/init.d/user-autorun</code>
В файле автозагрузки лучше указывать полный путь к исполняемому файлу, поскольку иначе при загрузке иногда возникают проблемы вида “firewall: command not found”.

Этот файл кладём в папку /etc/init.d/. Полный путь к нашему файлу автозагрузки — /etc/init.d/user-autorun. Осталось лишь указать системе, что нужно выполнять этот файл при загрузке:
<code class="bash">update-rc.d user-autorun defaults</code>
Эта команда заодно и проверяет, соответствует ли заголовок скрипта нужному, поэтому — если с этим будут проблемы, ничего в автозагрузку не поставится и придётся разбираться с ошибками. Всё, скрипт автозагрузки готов к работе и будет выполняться каждый раз при запуске системы, запуская скрипт маршрутизации. Конечно, в данном решении есть свои недостатки, вроде невозможности как-либо контролировать доступ пользователей к Интернету, кроме отключения-включения самого скрипта, но для случая переносного сервера плюс один и огромный — это просто работает, без вмешательства и стабильно, а альтернативные системы при надобности я ещё успею рассмотреть.
Удачной настройки!

Следующая статья, скорее всего, будет про написание простого веб-интерфейса на Python, используя web.py. Через этот интерфейс можно будет управлять NAT (правда, не превышая возможностей написанного скрипта), включать/выключать wvdial, отсылать смс и просматривать состояние модема… А также делать всё, до чего дойдут руки. Пока что пишу скрипт для взаимодействия с модемом и продумываю интерфейс таким образом, чтобы его было легко использовать даже на мобильных устройствах. Также в запасе есть почти готовая статья по настройке параметров энергосбережения ноутбука, используя cpufreqd. Стоит ли выкладывать её, будет ли актуально?
Аргументированная критика и дополнения к статье категорически приветствуются.


Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Перевод] Не паникуй (перевод главы книги «Passionate Programmer» by Chad Fowler)


Почему эта книга заслуживает перевода

Хочу поделиться своим мнением с хабрасообществом о книге «Passionate Programmer», перевод одной из глав которой представлен ниже. Книга вышла в 2009 году, но среди российских программистов она не очень широко известна, тем не менее многие, кто познакомился с ней, считают её очень достойной. Чад Фаулер (автор книги) выложился очень хорошо, чтобы передать читателям свой богатый опыт (на данный момент он CTO 6Wunderkinder, имеет более 20 лет стажа разработки и в виду своего большого опыта и круга интересов он желанный гость на Ruby- и IT-конференциях). Да, уже и не помню как нашёл эту книжку, но помню, что именно предисловие от Кента Бека (идейный вдохновитель Test Driven Development и Extreme Programming) послужило причиной прочитать её.

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

После прочтения книги я заинтересовался Чадом. Нашёл его блог в сети. Как оказалось, он начал выкладывать в нём главы из своей книги (на данный момент опубликовано 2 главы из 53). Я спросил разрешения на перевод для хабра, он ответил, что это хорошая идея, но только сначала мне надо отправить ему письмо с тем, что конкретно я хочу переводить (видимо это пожелание было как-то связано с тем издательством, где была опубликована книга). После моего ответа неделю было молчание, я отправил повторное письмо — ответа снова не было. Потом я получил от него приглашение на Wunderlist (сервис, за который он отвечает на данный момент). В общем, я посчитал, что если явного запрета не было, а эти главы уже и так находятся в свободном доступе, и он ещё не совсем про меня забыл, то делать перевод можно. В общем, если перевод сообществу окажется полезным, я продолжу переводить другие главы. В тексте возможны ошибки (делал вычитку несколько раз, но всё же вдруг), поэтому заранее прошу прощения и прошу сообщать мне обо всех проблемах через личные сообщения.



Не паникуй

Я начал свою карьеру программиста, потому что любил компьютерные игры. С тех дней, когда игры запускались с кассет на моём Commodore 64, я был просто зачарован их интерактивностью и тем насколько глубоко они могли погрузить игрока в свой мир. Я стеснялся признать этот факт, но с течением времени понял, что в этом нет ничего зазорного. Как бы то ни было компьютерные игры превратили для меня картинку с экрана монитора в нечто большее, с чем я чувствовал себя комфортно, и что меня приводило в восторг.

Самой любимой игрой был Doom от id Software. Особенно мне нравился режим игры по сети против других игроков — deathmatch. Желающие поиграть между собой могли подключиться друг к другу через модем по телефонной линии или через обычное последовательное подключение и вести поединок на небольших локациях. Я был очень хорош в deathmatch. Я даже шутил, что это могло бы стать моей профессией — настолько я хорош в нём был. На удивление, поединок с другими игроками при своей простой цели по факту достаточно сложен. Он требует использования как хороших технических навыков игры, так и психологии — как безумный микс шахмат и быстрой перемотки вперёд.

Самый лучший способ прокачать навыки в своём деле — наблюдать за тем, как работает мастер. В те времена моего увлечения Doom, был один такой мастер, который был известен под ироничным ником «Noskill» («Безумения» — игра слов прим. переводчика). Noskill был царствующим чемпионом в Doom. Люди со всей Северной Америки могли оплачивать недешёвые счета за телефонную связь, лишь бы попытать счастье сыграть с ним. Поединки сохраняли с помощью встроенной в Doom функции записи. Я пересматривал каждую из них.

Для меня разгадка секрета мастерства Noskill не заняла много времени. Конечно, он был очень хорош в самой игре, но также был очевидный ключ к его успеху — он никогда не паниковал. Doom был такой игрой, раунд в которой мог завершится за считанные секунды после своего начала. Это было реально быстро. Я помню свой первый deathmatch: появился-умер-появился-умер-появился-умер. Когда в конечном счёте я мог оставаться в живых более чем несколько секунд, я обнаруживал себя бесцельно бегущим по коридору, едва ли понимая, где сейчас нахожусь.

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

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

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

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

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

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

Да, я вынужден признать, что просто советовать отпустить панику в стрессовой ситуации проще, чем реально применять этот совет на практике. Это типа того как сказать кому-нибудь: «Просто будь счастлив». Конечно, это хороший совет, но как это сделать? Как вы можете избежать состояния паники, когда кажется, что всё вокруг рушится? Для ответа на этот вопрос, нам надо немного подумать о том, почему мы паникуем.

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

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

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

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

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

Действуй!

1. Начните вести журнал паники. Суть — перехватить панику до того, как она возникнет. Это возможно, если вы будете развивать своё «реал-тайм» осознание возникающих ощущений и эмоций. Я научился делать это, анализируя реакции и ситуации уже после случившегося факта. Я не настолько крут, чтобы запустить поток в «фоне» для анализа возникающих мыслей, но я обнаружил, что если практиковать анализ в «офлайне», я становлюсь всё лучше и лучше, делая анализ в реальном времени.

Говорить, что вы будете делать свою работу лучше, анализируя реакции, и реально делать это — две разные вещи. Ведение журнала поможет структурировать процесс. Каждый день в определённое время (используйте календарь с напоминанием!), открывайте текстовый файл и записывайте любую ситуацию, которая вызвала у вас панику, даже если это было что-то из мелочей. Один раз в неделю, просматривая составленный список, оцените долгосрочные последствия каждой ситуации, вызвавшей панику. Действительно ли стоило паниковать? Какой могла бы быть наиболее разумная реакция на эту ситуацию? Чтобы сделал герой в фильме о вашей жизни вместо паникёрства?

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

P.S. На хабре в 2009 году начинался проект перевода этой книги:
Страсть к программированию
Страсть к программированию. Глава 2. Благодарности
Страсть к программированию. Глава 3. Введение
Страсть к программированию. Часть 1 (Выбираем рынок). Начало
Страсть к программированию. Часть 1. Совет 2. Спрос и предложение
Страсть к программированию. Часть 1. Совет 3. Кодинг ещё не всё

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Emotiv Insight — нейроинтерфейс за 229$

Emotiv Insight — это стильный мозговой интерфейс. По сути это беспроводная гарнитура, считывающая электроэнцефалограмму мозга и преобразующая эти данные в простые команды. Всего за 10 дней она собрала на Кикстартере 635 000$ вместо намеченных 100 000$.
image

image
Устройство позволяет оптимизировать производительность мозга, измерять и контролировать когнитивные функции, а также может снизить уровень стресса.

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

image
В отличие от их предыдущей разработки — Emotiv EPOC, новое устройство изящнее, быстрее, умнее, легче и дружелюбнее к пользователю.

Emotiv Insight — единственное устройство на рынке, имеющее 5 ЭЭГ сенсоров и 2 датчика, позволяющие охватить ключевые области коры головного мозга: лобная кора (исполнительные функции), теменно-височные (слуховые, пространственные / координация), и затылочная часть (визуальная).
В нём используется специальный полимерный биосенсор, который обеспечивает большую электрическую проводимость сигналов мозга, но не требует никакого проводящего геля или физиологического раствора. Таким образом, нет необходимости в какой-либо подготовке вообще. Т.е. датчик можно использовать сухим.

SDK для разработчиков и исследователей

За 299$ кроме самого нейроинтерфейса можно получить и SDK для разработки, включающий в себя драйвера, полное описание API, а также инструменты для анализа ЭЭГ.

Новая цель 6-ти осевой инерциальный датчик

На волне успеха, компания решила поставить новую цель перед своими фанатами. Если проект наберёт больше миллиона долларов, то устройство будет полностью переконструировано, чтобы добавить в него новый 6-ти осевой инерциальный датчик (roll, pitch, yaw, vertical, lateral, longitudinal acceleration), причём это не повлияет на цену конечного устройства.

Включение этих дополнительных функций позволит приложениям:
  • отслеживать сложные движения головы;
  • управлять камерой и движением в реальном и виртуальном окружении — полное управление над 3D курсором в CAD-пакетах, летных симуляторах и дистанционное управление транспортными средствами
  • автоматически распознавать жесты — кивок ДА, встряхнуть головой НЕТ, пожатие плечами и другие жесты;
  • возможно, даже получать частоту дыхания и сердцебиения;
  • анализировать походку и дрожание.

Технические характеристики

image

План работы

image

Вполне, возможно, что скоро мы увидим помесь Emotiv Insight и Google Glass.

UPD. Цена доставки в любую точку мира составляет 30$

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Внешний сервис голосования aka like-dislike feature

Добрый день, Хабрасообщество!

В процессе реализации одного моего проекта (с блекджеком и всеми остальными social прелестями), пришлось реализовывать функциональность голосования (like, like/dislike, rating, etc) пользователей за некоторые сущности предметной области проекта.

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

Поискав в Google готовые решения, не удалось найти ничего подходящего. В основном решения (плагины для различных web-фреймворков) сводятся к добавлению дополнительных полей в существующие таблицы (или объекты коллекций в случае MongoDB), в которые пишется количество лайков/дислайков, а также кто из пользователей уже проголосовал. Такие решения имеют значительные недостатки, так как с одной стороны не обладают достаточной гибкостью, позволяющей легко модифицировать алгоритмы голосования (что очень важно для нового проекта в процессе поиска правильной модели), а с другой стороны требуют модификации существующего кода и, что еще хуже, уровня хранения данных, для добавления функциональности голосования.

В то же время, существует значительное число сервисов, предоставляющих возможности по добавлению комментариев на свой сайт, как то cackle.me, disqus.com и пр. Сервисы являются внешними по отношению к разрабатываемому проекту и позволяют минимальными усилиями добавить возможность комментировать что угодно на своем сайте (или в приложении).

Возник логичный вопрос, почему не существует аналогичных сервисов по добавлению голосовалок на свой сайт?

Функции, необходимые, сервису голосовалок
  • внешнее API
  • хранение данных на стороне внешнего сервиса
  • возможность отложенной выгрузки данных по голосам
  • решение классических вариантов использования like/dislike на стороне внешнего сервиса
    • голосование (лайк) пользователя за какой-то объект
    • все голоса (лайки) за заданный объект

    • все голоса пользователя (когда, за какие объекты, как)
    • при построении списка объектов, получить информацию, за какие из объектов голосовал текущий пользователь и с каким результатом
    • при построении списка объектов, получить информацию, о количестве лайков/дислайков или количестве оценивших на 1,2,3,4,5 звезд для каждого из объектов
Таким образом, основную логику обработки лайков или рейтингования берет на себя внешний сервис. Например, он должен проверять, не является ли лайк пользователя за заданный объект повторным и не давать выполнить такое голосование. При этом бизнес логика кто и за что может голосовать может быть реализована уже на стороне собственного проекта.

Из дополнительных возможностей хотелось бы видеть:
  • Возможность отдельно голосовать за определенные аспекты объектов (теги).
  • Версионность голосования (удобно для сплит-тестирования, для одной группы пользователей разрешаем лайки и дислайки, а для другой только лайки и наблюдаем за поведением пользователей на сервисе).
  • Добавление событий в очередь сообщений о новых лайках, на которые можно подписываться и отложенно их обрабатывать (для пересчетов рейтингов в фоновом режиме, например).
Интеграция сайта с сервисом
Думаю, должно быть 2 способа — со стороны бекенда и со стороны фронтенда (веб-клиента или мобильного клиента). Так как можно вообще не хранить на своей стороне информацию о голосах, можно делать запросы на создание лайков или получение количества лайков за объекты прямо с клиента (идентифицируя себя каким-либо токеном). Таким образом страничка будет собираться из нескольких источников. Также можно собирать информацию о голосах на бекенде и инжектить ее в результирующие данные перед отправкой их на клиент, делая запросы к внешнему API. Возможно даже асинхронные, чтобы во время ожидания ответа можно было выполнить прочую обработку данных.

Должны существовать плагины для популярных языков (Ruby, PHP, JS) позволяющие за счет миксинов или же просто добавления новых модулей в проект легко добавлять возможность лайкать/дислайкать или оценить объекты предметной области.

Преимущества
  • Никакой лишней информации о голосах в существующих структурах данных на уровне хранения.
  • Минимум кода для добавления возможности голосовалки на свой сайт или мобильное приложение.
  • Возможность интеграции исключительно средствами клиента.
  • Снимает часть нагрузки с бекенд-серверов.
  • Несколько моделей голосования одновременно (удобный механизм для сплит-тестов).

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

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Релиз elementary OS «Luna»

Спустя два с половиной года, после релиза elementary OS с кодовым именем «Jupiter», вышла новая версия, с кодовым именем «Luna». Дистрибутив основан на Ubuntu 12.04 LTS, поэтому проблем совместимости с пакетной базой Ubuntu 12.04 не будет.


Первая версия elementary OS была основана на Ubuntu 10.10 и имела рабочее окружение GNOME 2.
В Luna уже используется GTK3+ и GNOME 3.

В состав дистрибутива включены следующие приложения:
Софт собственной разработки проекта elementary OS:
  • Оболочка рабочего стола Pantheon
  • Оконный менеджер Gala
  • Эмулятор терминала Pantheon Terminal
  • Файловый менеджер Pantheon Files
  • Текстовый редактор Scratch
  • Музыкальный проигрыватель Noise
А также сторонние приложения, входящие в состав дистрибутива:
  • Браузер Midori
  • Почтовый клиент Geary
  • IM-клиент Empathy
  • Менеджер фотографий Shotwell
Основное внимание в дистрибутиве уделяется дизайну и минимальному потреблению ресурсов. Разработчики утверждают, что 512M оперативной памяти будет достаточно для нормальной работы системы.

Хоть система проста в использовании, выглядит презентабельно, однако, некоторые приложения все же придется доустанавливать самому (например офис, GIMP), хотя, это скорее плюс, ведь у вас есть выбор.
Дистрибутив довольно популярен, на данный момент занимает 28ю строчку в рейтинге популярности дистрибутивов на distrowatch.com за последний месяц.





для скачивания:
ISO: x86 | amd64
Torrent: i386 | amd64

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Дети не могут использовать компьютеры… И вот почему это должно вас беспокоить

Многобукв? Что ж, почему бы вам не посмотреть пятисекундное видео с котенком, засунувшим голову в рулон туалетной бумаги, или прочитать 140-символьное описание блюда, которым ваш друг набил себе рот. «Ням-ням». Этот пост не для вас.

В рабочем кабинете зазвонил телефон. Это был один из школьных секретарей, объяснивший, что внизу посетитель, которому нужно подключиться к школьной WiFi сети. iPad в руки, и я рысью бросился вниз в приемную, чтобы увидеть молодую особу двадцати с лишним лет, сидящую в кресле с MacBook-ом на коленях.

Я улыбнулся и представился, присаживаясь рядом с ней. Она без слов вручила мне MacBook, и выражение ее лица сказало всё: «Почини мой компьютер, гик, и побыстрее». Меня путали с техником достаточное количество раз для уверенного распознавания этой гримасы.

— Придется поторопиться. Через 5 минут у меня урок, — сказал я.
— Вы преподаете?
— Это моя работа, просто так получилось, что также приходится управлять командой специалистов по сетям.

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

Я посмотрел на MacBook. На тот момент у меня не было опыта с OS X. Но Джобс не был идиотом, и то, что отображалось в верхнем правом углу экрана, было общеизвестным символом WiFi. Чтобы подключить устройство к сети, мне понадобилось несколько секунд.

Вручил MacBook обратно, и женщина открыла Safari. «Интернет не работает», заявила она с презрением.

Я уже столько раз слышал эту фразу от учеников и персонала, что у меня заготовлена стандартная реакция. Обычно я достаю свой сотовый телефон, делаю вид, что набираю номер. И подняв трубку к уху, говорю: «Да, соедините меня с офисом Президента Соединенных Штатов… НЕТ, Я НЕ МОГУ ПОДОЖДАТЬ, это чрезвычайное происшествие… Алло, Мистер Президент, боюсь у меня плохие новости. Меня только что проинформировали, что Интернет не работает».

Но я решил, что молодая женщина наверное не оценит сарказм, и забрал MacBook обратно, чтобы добавить настройки прокси-сервера. Без каких-либо идей, как это сделать в OS X. Прокси у нас используется, чтобы убедиться, что персонал и ученики не могут получить из школьной сети доступ к порно. Также он фильтрует насилие, экстремизм, ругательства, социальные сети, алкоголь, курение, хакерство, игры и потоковое видео. Забавно, что когда вы ищете в Google «proxy settings OSX», результаты выдачи будут заблокированы, поскольку содержат слово «proxy», а оно фильтруется.

«Вы не знаете, где здесь настройки прокси?» — спросил я с надеждой.

Ответа я не получил. С тем же успехом можно было спросить у нее «Не подскажете, как мне ретикулировать сплайны с использованием гексагональной системы декодирования, чтобы я мог создать GUI на VisualBasic и отследить IP-адрес?»

корни шуткиспасибо acherneha — прим. переводчика.

Настройки прокси я нашел и заполнил за десять секунд. Вернул ей MacBook, и она, буквально, закрыла Safari и открыла его заново, вместо того, чтобы обновить страницу. «Пасиб…». Благодарность ее была ошеломляющей.

Я уже уходил, когда она меня остановила. «PowerPoint не работает».


Это, наверное, уже не дает права на телефонный звонок Президенту Соединенных Штатов. Я уверен, что он интересуется технологическими проблемами, но падение ведущего мирового инструмента для презентаций будет для него скорее чем-то вроде облегчения, пожалуй. Хотя бы АНБ не будет терять убого оформленные слайд-шоу.

NSA PowerPoint slide
Пришлось сесть обратно и снова завладеть ее MacBook-ом. Слайд, который она открыла, содержал встроенное видео с YouTube, а как я уже сказал, потоковое видео блокируется. Я попытался объяснить это женщине, и тогда она покровительственно мне растолковала, что это не имеет значения, потому что видео было в ее PowerPoint-е и воспроизводилось с ее флешки. Спорить не стал, это не стоило моего времени. Лучше сделать то, что я обычно делаю для людей, и просто заставить это работать. Используя 3G подключение моего iPad-а, я настроил точку доступа, скачал ролик с YouTube, используя популярный сервис для скачивания, и потом встроил локальное видео в ее презентацию.

— И чему вы учите? — спросила она, пока я работал над ее презентацией.
— Вычислительная техника — ответил я.
— О… Я думаю в наше время вы сталкиваетесь с тем, что дети знают о компьютерах больше, чем учителя…

Если вы обучаете информационным технологиям или вычислительной технике, это фраза, которую вы слышали миллион раз, миллиард раз, зиллион раз. Ладно, я преувеличиваю, но вы слышали это много раз. Существуют разные варианты этой фразы, все поддерживающие технические способности сегодняшних детей. Мои любимые — от родителей. «О, Джонни без труда станет лучшим специалистом по компьютерам, он постоянно сидит дома за компьютером». У родителей, похоже, есть смутная теория, что проведение нескольких часов каждый вечер за фейсбуком и ютьюбом передает, через особый вид кибернетической жидкости, знание PHP, HTML, JavaScript и Haskell-я.

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

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

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

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

Шестиклассник приносит мне свой ноутбук, объясняя, что тот работает очень медленно и отключается. Ноутбук буквально визжит, кулеры крутятся на всю катушку и корпус некомфортно горячий на ощупь. Запускаю Диспетчер задач и вижу, что CPU загружен на 100%, хотя запущен только uTorrent (у которого, внезапно, 200 торрент-файлов на раздаче). Осмотрелся, какие процессы запущены, и их было много, жрущих CPU и RAM. Более того, я не мог выключить ни одного из них. «Какой антивирус ты используешь?» — спросил я, чтобы услышать, что он не любит антивирусы, поскольку они замедляют работу компьютера. Я вернул ему ноутбук, и сказал, что тот заражен. Он спросил, что ему нужно сделать, и я предположил, что ему следует переустановить Windows. Он посмотрел на меня беспомощно. Он не может пользоваться компьютером.

Девочка подняла руку на уроке. «Мой компьютер не включается», сказала она. С отчаянием в голосе, подразумевающим, что она испробовала все мыслимые способы заставить железяку работать. Я подошел, включил монитор, и экран ожил, отображая окно авторизации в Windows. Она не может пользоваться компьютером.

Учительница принесла мне свой ноутбук. «Чертова железка не подключается к интернету», сказала она со злостью, как будто это моя вина. «Мне надо было сделать тонны работы прошлой ночью, но я вообще не могла выйти в сеть. Даже мой муж пробовал и не смог ничего сделать, а он отлично разбирается в компьютерах». Я взял провинившийся ноутбук, переключил выключатель беспроводной сети, расположенный на боковой кромке, и вернул ей обратно. Ни она ни ее муж не могут пользоваться компьютером.

Ребенок постучался в дверь моего офиса, и пожаловался, что не может авторизоваться. «Ты забыл пароль?», — спросил я, но он настаивал на том, что это не так. «Какое было сообщение об ошибке?», спросил я. Он пожал плечами. Я пошел с ним в IT-крыло, и смотрел, как он вводит логин и пароль. Появилось окно с сообщением, но ребенок нажал OK настолько быстро, что я не успел прочитать. Процесс повторился три раза, как будто компьютер внезапно может изменить свое мнение и разрешить доступ к сети. На третьей попытке я мельком рассмотрел сообщение. Забрался за его компьютер и воткнул кабель Ethernet. Он не может пользоваться компьютером.

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

Учитель позвонил мне в офис, жалуясь, что в его ноутбуке «нет интернета». Я спустился в его класс. Он сказал, что вчера интернет был, а сегодня исчез. Его рабочий стол — сплошная стена иконок документов Microsoft Office, расположенных беспорядочно. Я попытался быстро объяснить, что рабочий стол — не лучшее место для хранения документов, поскольку они не зарезервированы на сервере, но его это не волновало, он просто хотел интернет обратно. Я открыл стартовое меню и щелкнул на Internet Explorer, тот открылся и отобразил домашнюю страницу. Коллега объяснил, что интернет был на рабочем столе, но теперь отсутствует. Я закрыл IE и осмотрел рабочий стол, обнаружив в итоге маленькую голубую «e», захороненную среди иконок PowerPoint и Excel. Указал на нее. Коллега указал на другое место на экране, и заявил, что иконка должна быть там. Я перетащил иконку в нужную позицию. Он счастлив. Он не может пользоваться компьютером.

Ребенок поднял руку. Сказал мне, что на его компьютере вирус. Я посмотрел на экран. То, что отображалось в веб-браузере, выглядело как диалоговое окно XP, предупреждающее о том, что компьютер заражен и предлагающее скачать программное обеспечение для сканирования и удаления вирусов. Он на машине с Windows 7. Я закрыл злобную закладку. Он не может пользоваться компьютером.

Не уметь пользоваться компьютером считается приемлемым, если вам двадцать пять лет или больше. Это нечто такое, чем некоторые люди извращенно гордятся, но широко распространенная мудрость гласит, что все, кто моложе 18, являются техническими волшебниками, и это просто не правда. Они могут использовать некоторое программное обеспечение, в частности — веб-приложения. Они знают, как использовать Facebook и Twitter. Они могут использовать YouTube и Pinterest. Они также знают, как использовать Word и PowerPoint и Excel. Попроси их переустановить операционную систему — и они потерялись. Попроси их заменить жесткий диск или оперативную память — и они покрываются холодным потом. Спроси их, что значит https и почему это важно — и они посмотрят на тебя так, будто ты говоришь на Клингонском.

Они жмут «OK» в диалоговых окнах, не читая сообщение. Они выбирают пароли типа qwerty1234. Они отключают компьютер, удерживая кнопку выключения, пока монитор не погаснет. Они оставляют компьютер с открытой сессией выходя из комнаты. Если программа зависает, они жмут одну и ту же кнопку снова и снова, пока все не навернется окончательно.

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

Родители
Я облажался, и я уверен, что многие из вас тоже. Когда мы купили Xbox, это было Техно-Папа спешит на помощь. Я радостно игрался с кучей кабелей и потом посоздавал профили для всех. Когда MacBook моего сына был заражен FlashBack-ом — Техно-Папа спешит на помощь. Я просмотрел пару онлайн-руководств и забился глубоко в терминал, пока не искоренил этого плохиша. Когда мы купили «Family Raspberry Pi» — Техно-Папа спешит на помощь. Я все это собрал, прошил ОС на SD-карту и гордо расселся, удивляясь, почему никто кроме меня не хочет использовать проклятую штуковину. Всю их жизнь, я делал это для них. Устанавливал новое оборудование, новое программное обеспечение, и действовал как домашний техник, как только что-то шло не так. В итоге, у меня семья цифровых неучей.

Школы
Когда стало понятно, что компьютеры становятся важными, правительство Великобритании признало, что ИТ наверное должны стать частью основного учебного плана в школах. Являясь стадом ИТ-неучей, политики и советники обратились к индустрии с вопросами, что нужно включить в новый план. На тот момент, была только одна индустрия, и это была монополия Microsoft.
<сарказм>
В Microsoft долго и напряженно думали насчет того, что должно быть включено в учебный план, и после осторожного обсуждения они выдвинули совет, что ученикам действительно нужно научиться пользоваться офисным программным обеспечением
</сарказм>
. И появился новый учебный план.
<сарказм>
Школы долго и упорно искали правильное офисное программное обеспечение для изучения, и тщательно всё взвесив, они выбрали Microsoft Office
</сарказм>
. Так что с 2000 школы обучали учеников навыкам Microsoft (навыки Adobe были введены чуть позднее).

Но учебный план — не единственная область, где мы облажались. Наши сетевые инфраструктуры в школах Великобритании — это позор. Мы скопировали корпоративные сети, ограничивая доступ детей и учителей к системным настройкам, к командной строке, и требуя права администратора чтобы сделать что-либо. Они сидят за компьютерами общего назначения без возможности выполнять задачи общего назначения. У них есть доступ к нескольким приложениям, и это всё. Доступ компьютеров к интернету через прокси-сервера, которые агрессивно фильтруют всё менее пушистое, чем Википедия, и большинство школ используют еще и дополнительное ПО для фильтрования поверх этого, так что они могут использовать белые списки «подходящих сайтов».

Windows и OS X
Мой первый ПК был ESCOM P100 с Windows 3.1. Мой второй был Packard Bell с Windows 95. Мой третий был собран самостоятельно, с Windows XP. Четвертый — ноутбук Acer с Windows 7. Сейчас я использую MacBook Pro с OS X (или иногда Ubuntu, в зависимости от настроения и уровней паранойи). Windows 7 была для меня переломным моментом. Это был первый раз, когда я установил ОС, и мне не надо было буквально ничего конфигурировать. Даже физрук мог бы с этим разобраться.

Windows 7 (я ненавижу 8, но это другая история) и Mac OS X — отличные операционные системы. Их легко использовать, почти не требуется настройка, в них уже включены или легко доступны все драйверы, и всё в основном «просто работает». Это фантастика, что каждый, от маленького ребенка до старого дедушки теперь может использовать компьютер, обладая абсолютным минимумом технической грамотности. Но это также катастрофа. Раньше было по другому. Использование ОС было тяжелой работой. Когда что-то шло не так, вам приходилось нырнуть и испачкаться, чтобы все починить. Вы узнавали о файловых системах, настройках реестра и драйверах для вашего оборудования. Больше не надо.

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

Мобильные технологии
Мобильные технологии убили технические умения. Теперь мы носимся с компьютерами, которые прикидываются сотовыми телефонами или планшетами. Большинство людей даже не думают о своем телефоне, как о компьютере. Это устройство, которое дает быстрый доступ к Google. Это устройство, позволяющее нам делать фотографии и публиковать их в Facebook. Это устройство, на котором мы играем в игры и публикуем рекорды в Twitter. Это устройство, которое блокирует файловую систему (или прячет ее от нас). Это устройство, которое позволяет устанавливать только дезинфицированные приложения через регулируемый магазин приложений. Это устройство, компоненты которого не могут быть обновлены или заменены, и устареют через год или два. Это устройство такой же компьютер общего назначения, как игрушка Fisher Price, которая у меня была, когда мне было три года.

image

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

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

Нет самолетов, есть только компьютеры, которые летают. Нет автомобилей, есть только компьютеры, в которые мы садимся. Нет слуховых аппаратов, есть только компьютеры, которые мы вставляем в наши уши.
Лето Слежки меня обеспокоило.


Когда откровения Сноудена впервые появились, я пришел в школу в понедельник и обнаружил, что большинство моих коллег и учеников либо не слышали о скандале, либо их это не беспокоило. Пока я был занят удалением моих онлайн-акаунтов и блокированием моих компьютеров, друзья называли меня параноиком и шутили о шапочках из фольги. Мои родные пожимали плечами и бормотали часто цитируемое «Нечего скрывать, нечего бояться». Потом, внезапно, Кэмерон объявил, что провайдеры начнут фильтровать Интернет. Это описывается как «фильтр порно», но результаты расследования Open Rights Group показывают, что по умолчанию будет фильтроваться намного больше, чем порно. Потом, в завершение истории, взломали сайт главной советницы Кэмерона по этой проблеме, и показали, насколько она в действительности технически неграмотна.

Завтрашние политики, госслужащие, полицейские, учителя, журналисты и директора — создаются сегодня. Эти люди не знают, как использовать компьютеры, и при этом они собираются создавать законы относительно компьютеров, защищать законы о компьютерах, обучать молодежь компьютерам, освещать компьютеры в СМИ и лоббировать политиков насчет компьютеров. Вы думаете это приемлемый расклад дел? Дэвид Кэмерон говорит мне, что фильтрование интернета — хорошая штука. Уильям Хог (William Hague) говорит мне, что мне нечего бояться GCHQ. У меня один вопрос к этим политикам:

Без обращения к Википедии, можете ли вы сказать, в чем разница между Интернетом, World Wide Web, веб-бразуром и поисковым движком?
Если вы не можете — то вы не имеете права принимать решения, затрагивающие эти технологии. Попробуйте. Ваши друзья знают разницу? А вы?

Наводим порядок

Родители
Перестаньте решать проблемы за ваших детей. Вы тратите многие часы вашего времени, приучая их к ночному горшку, пока они маленькие дети, поскольку способность использовать туалет является важным навыком в современном обществе. Вам надо поступить так же с технологиями. Обязательно купите им компьютер, но есть что-то пойдет не так — пусть они это чинят. Купите им смартфон, дайте ?10/год на баланс в магазин приложений, и пусть сами узнают, почему in-app покупки — плохая идея. Когда мы учим детей ездить на велосипеде, в определенный момент надо снять тренировочные колесики. Вот идея. Когда им стукнет одиннадцать, дайте им текстовый файл с десятью тысячами паролей WPA2, и скажите, что один из них настоящий. Посмотрите, как быстро они откроют для себя Python или Bash.

Школы
В Великобритании мы некоторым образом движемся к решению проблемы. У меня с Говом (Michael Gove, прим. переводчика) сложные отношения, но мне искренне нравится, что он делает с учебным планом по компьютерным наукам. Нам надо только убедиться, что руководство поддерживает компьютерные науки, и не использует реформу учебного плана как повод сэкономить деньги путем объединения предметов.

Мы также можем делать больше. Мы должны учить детей не устанавливать зловредное ПО несколько иначе, нежели блокировкой машин таким образом, чтобы это было физически невозможно. Мы должны учить детей оставаться в безопасности онлайн, вместо фильтрования их интернета. Google и Facebook дают детям деньги, если те находят и используют уязвимости в безопасности их систем. А мы за попытки взлома исключаем детей из школы. Это правильно?

Windows и OS X
Используйте Linux. Хорошо, это не всегда практично, но большинство дистрибутивов Linux реально заставят вас научиться, как использовать компьютер. Каждому нужно хотя бы поиграться с этим в определенные моменты жизни. Если вы не собираетесь использовать Linux и вы на OS X — поиграйтесь в терминале, это реально весело и вы почувствуете себя хакером, также как и в Командной строке или PowerShell в Windows.

Мобильные технологии
Здесь сложно. iOS — гиблое дело, если вы не сделали jail-break, Android не намного лучше. Я использую Ubuntu Touch, и у нее есть перспективы. Как минимум вы будете чувствовать, что сотовый телефон — ваш. Да, я не могу использовать 3G, оно падает, когда я пытаюсь позвонить, и устройство настолько нагревается, что при расположении в кармане пиджака, его вторая функция — разогреватель сосков, но я вижу потенциал.

Итоги

Это уже случалось ранее. Это не новый феномен. Сотню лет назад, если вы были счастливчиком, который владел автомобилем, вы наверняка знали, как его починить. Люди могут как минимум заменить масло, заменить шины или настроить двигатель. У меня был автомобиль большую часть моей взрослой жизни, и это всё для меня загадка. Я зависим от продавцов, которые скажут мне, что купить, от механиков, которые скажут, что сломалось и починят это за меня, а по мере развития технологий, я становлюсь зависим также от спутниковой навигации. Сомневаюсь, что моему пятилетнему сыну вообще придется учиться водить. Его автомобиль будет делать это за него. Когда ему понадобится что-то починить, он будет отправлен к механику, который больше заплатил за онлайн-рекламу. Когда он захочет остановиться перекусить, он будет отправлен в закусочную, которая больше заплатила за онлайн-рекламу. Когда ему надо будет перезарядить его дилитиумовые кристаллы — он будет отправлен на заправочную станцию, которая больше заплатила за онлайн-рекламу.

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

© Marc Scott, Jul 29th, 2013

Upd.: Подскажите кто-нибудь в личку, как правильно оформить топик-перевод. И как вставить видео с YouTube, копипаст предлагаемого HTML-кода не работает…

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Nokia HERE LivingCities



Хорошего дня, Хабр!

Мы снова в эфире и на этот раз хотим рассказать вам об одном интересном проекте Nokia HERE LivingCities, созданном совместными усилиями команды локационного сервиса HERE и нашими друзьями и партнерами из облачного сервиса картографии, аналитики и визуализации CartoDB.

Многие из нас привыкли к тому, что город часто сравнивают с живым существом — созданием, обязанным человеку своим появлением на свет, но не подчиняющимся ему, а, наоборот, подчиняющим. Созданием, у которого есть свой характер, душа, сердце и, что самое главное, сложная система «вен и артерий»: улиц, дорог, магистралей, развязок и колец, которые и позволяют любому городу жить и дышать. Мы решили узнать, что на самом деле представляет собой жизнь города и обработали множество различных данных в пяти мегаполисах: Лондоне, Чикаго, Риме, Хельсинки и Мумбае. Всю полученную информацию мы, благодаря CartoDB, нанесли на специальную виртуальную карту в формате суточного timelapse.




Данные, которые легли в основу проекта, постоянно собираются нашей платформой HERE с помощью подключенных к ней устройств — смартфонов пользователей (разумеется, анонимно) и наших партнеров-поставщиков, подробнее о которых мы уже рассказывали. Визуализация создана с помощью облачной инфраструктуры CartoDB с использованием HTML5 для анимации геолокационных данных за определенные периоды.

Проект Living Cities показал, что цифры могут поведать много интересных историй, даже о том городе, о котором, казалось, вы знаете всё. Например, выяснилось, что Мумбаи спит всего 2 (!) часа в сутки — между часом и тремя ночи.



Второе место после Мумбаи по совокупному времени активности его населения занимает Лондон, хотя в этом случае скорое всего ничего необычного: город живет в ритме культурной и деловой столицы и поэтому просыпается около 5 утра. Рим начинает заниматься делами немного позже, в 7.30 утра, что только подтверждает некоторые стереотипы о столице Италии.

Можно было бы ожидать, что только в таком относительно небольшом городе, как Хельсинки, ночь наступает по графику, но наш эксперимент показывает, что активность Чикаго также начинает идти на спад довольно рано.

Есть много других интересных данных. Например, мы узнали, что средняя скорость в Лондоне составляет 24,7 километра в час, а Рим — это настоящий рай для гурмана — здесь насчитывается около 2100 ресторанов.



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



Ну а для нас, это хороший способ улучшить свои сервисы и попытаться понять коллективное поведение. Разумно предположить, что это лишь малая доля того, каким образом можно использовать эту информацию. Но как говорит Рено Мариони из команды HERE: «Мы находимся в начальной стадии рассмотрения того, что мы можем сделать с данными такого рода. И наш проект — это красивый холст для поиска различных возможностей применения».

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Перевод] Создание Recovery раздела после установки Mac OS

Mac OS X Lion и Mountain Lion< не всегда при своей остановке предлагают создать Recovery Partition (не путать с внешним диском восстановления). Затем, пользуясь Маком и вникая в его функции Вы узнаете, что оказывается FileVault 2 (шифрование дисков) и Find My Mac (функция дистанционного нахождения и очистки мака) — не работают при отсутствии раздела восстановления непосредственно на системном диске.

Cоздать его по факту, без реинсталляции ОС, штатным средствами невозможно. Очень непохоже на Apple, но это факт. Из более не менее здравых и адекватных способов я нашел лишь один:



Подготовка папки Downloads

1. Необходимо скачать Lion Recovery Update и поместить его в папку Downloads.

2. Затем необходимо раздобывать инсталлятор OS X Installer.app. В Finder кликаете правой кнопкой мыши и Show Package Contents, затем заходите по пути Contents/SharedSupport, находите файл InstallESD.dmg и помещаете его в Downloads

3. Копируете вот этот код в текстовый редактор и сохраняете его как «recovery.sh» в ту же папку Downloads:

read -p «Ensure „RecoveryHDUpdate.dmg“ and „InstallESD.dmg“ are in your Downloads folder and press [Enter]»

#access dmtest from RecoveryHDUpdate.pkg
rm -rf /private/tmp/RecoveryHDUpdate
echo «Expanding RecoveryHDUpdate.pkg»
hdiutil attach -nobrowse ~/Downloads/RecoveryHDUpdate.dmg
pkgutil --expand /Volumes/Mac\ OS\ X\ Lion\ Recovery\ HD\ Update/RecoveryHDUpdate.pkg /tmp/RecoveryHDUpdate

#access BaseSystem.dmg and BaseSystem.chunklist
echo «Expanding InstallESD.dmg»
hdiutil attach -nobrowse ~/Downloads/InstallESD.dmg

#build Recovery partition
echo «Building Recovery Partition. Please Wait»
/tmp/RecoveryHDUpdate/RecoveryHDUpdate.pkg/Scripts/Tools/dmtest ensureRecoveryPartition / /Volumes/Mac\ OS\ X\ Install\ ESD/BaseSystem.dmg 0 0 /Volumes/Mac\ OS\ X\ Install\ ESD/BaseSystem.chunklist

#cleanup
echo «Cleaning up»
hdiutil eject /Volumes/Mac\ OS\ X\ Lion\ Recovery\ HD\ Update
hdiutil eject /Volumes/Mac\ OS\ X\ Install\ ESD/
sudo touch /Library/Preferences/SystemConfiguration/com.apple.Boot.plist
sudo kextcache -f -u /
exit 0

Сам экшн

1. Открываем Terminal и вводим:

chmod +x ~/Downloads/recovery.sh

sudo ~/Downloads/recovery.sh
2. Перезагружаетесь.

3. Готово! Filevault 2 и Find My Mac работают!

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Перевод] Чем тестировать адаптивный дизайн?

image

Хватит менять размер окна браузера, хватит его насиловать! Готов спорить, вы не раз слышали это. Хорошо, возможно и не слышали. Но если вы профессионально занимаетесь разработкой адаптивных сайтов, вы понимаете о чем я: любое изменение DOM или правка CSS, и вы снова начинаете тянуть край браузера вперед, назад, тестируя изменения и просматривая ничего ли не сломалось.

Целью ваших движений является имитация экранов различных устройств.

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

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

Для тестирования я выбрал реально адаптивный сайт PajamasOnYourFeet.com, сайт построено на основе HTML5 шаблона, бесплатно предоставленным EGrappler.

Am I Responsive?

Am I Responsive, очень простой инструмент, позволяющий быстро просмотреть ваш сайт на 4 устройствах. Все они — IOS и разработчик объясняет это фишкой сайта. В общем никаких настроек, никакого выбора, а очень просто и наглядно.

Доступные размеры:
  • настольный монитор — 1600 x 992px;
  • ноутбук — 1280 x 802px;
  • планшет — 768 x 1024px;
  • мобильный телефон — 320 x 480px.
Цитирую разработчика: «это не инструмент для тестирования, крайне важно проводить тестирование на реальных устройствах. А данный инструмент поможет быстро сделать скриншот и показать клиенту, что вы имеете ввиду».

Есть две приятные фишки: возможность таскать устройства по вашему экрану, а также возможность поделится ссылкой на тест сайта.

image

deviceponsive

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

Устройства и доступные расширения экранов.
  • Macbook — 1280 x 800
  • iPad портрет — 768 x 1024
  • iPad портрет — 1024 x 768
  • Kindle портрет — 600 x 1024
  • Kindle альбомная ориентация — 1024 x 600
  • iPhone портрет — 320 x 480
  • iPhone альбомная ориентация — 480 x 320
  • Galaxy портрет — 240 x 320
  • Galaxy альбомная ориентация — 320 x 240
Как и на большинстве подобных инструментах отображаются полосы прокрутки, которых бы не было бы на реальных устройствах. Это вынужденный шаг для обеспечения возможности прокрутки на не сенсорных устройствах.

image

responsive test

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

30 различных разрешений доступно на сайте, начиная от огромного настольного монитора, до того, что они называют «дрянный андроид» (справедливости стоит заметить, что есть и нормальный андроид).

Что касается браузера Firefox, то он немного не корректно работает с данным сайтом. Обратите внимание, что на скриншоте не отображается слайдер между зеленым заголовком и белой областью фонового содержания.

image

responsive.is

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

Доступные варианты устройств — авто (то как вы видите сайт), настольный комьютер, планшет в альбомной и портретной ориентации, смартфон в портретной и альбомном положении. Задавать произвольные размеры в px, к сожалению нельзя.

image

Screenqueries

А вот возможности и доступные опции отличают Screenqueries от предыдущих сервисов. 14 телефонов и 12 планшетов представлены здесь, с отдельной возможностью переключения в портретный и альбомный режим. Результаты отображаются на сетке с линейками. Также возможно задать произвольное разрешение, потянув за правый или нижний край.

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

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

image

Screenfly

Screenfly пожалуй наиболее функциональный из всех. Доступно 9 больше чем планшет устройств — от 10" ноутбуков, до 24" мониторов, 5 планшетов, 9 телефонов, 3 телевизионных разрешения, а также произвольное разрешение. Добавьте сюда отдельный переключатель в портретный и альбомный режим, а также опцию показа прокрутки. Также можно поделится ссылкой на тест с помощью одной кнопки.

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

Все перечисленные достоинства позволяют претендовать на лидерство если бы не одно но (цитата разработчика): «Screenfly может использовать прокси-сервер, чтобы имитировать устройства во время просмотра вашего сайта. Прокси-сервер имитирует строку агента пользователя, но не поведение этих устройств.» Screenfly является единственным сервисом из списка, который позволяет тестировать на основе строки агента пользователя.

image


Используете ли вы представленные инструменты в своей практике? Делитесь своими секретами разработки адаптивных сайтов в комментариях.

P.S. Ошибки по поводу перевода просьба сообщать в личку.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Создание башкирской раскладки для Mac OS X

Смена операционной системы или устройства, если вы пишете на каком-нибудь не очень распространенном языке, например, башкирском — это всегда сложности. Поэтому, люди до сих пор сидят на Windows XP, с криво прописанными в реестре кастомными раскладками и столь же кривыми «башкирскими» шрифтами. Ведь хоть и криво, но работает. Много лет и я сидел на Windows и как-то даже не вспоминал о существовании проблемы, но пересев на Mac, обнаружил, что по умолчанию в OS X башкирской раскладки нет. Пошел искать кастомную в Интернете, где меня тоже ждало разочарование. Как же так, вроде столько лет прошло? В итоге, как это уже однажды было с Android, решил сделать все самостоятельно.

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

image



Башкирский алфавит

Для того, чтобы лучше представлять о чем дальше будет идти речь, сначала взглянем на башкирский алфавит. Всего в нем 42 буквы, из них 33 буквы русского алфавита + 9 дополнительных. На мой взгляд — это очень много, тем более что некоторые буквы используются только для заимствований из русского. Такая избыточность не позволяет комфортно разместиться на клавиатурах. В целом такая же проблема есть у многих народов на территории бывшего СССР, испытавших на себе влияние сталинизма.
image

Принципы используемые при создании раскладки

Прежде чем начать работу, нужно постараться сформулировать простые принципы, от которых можно отталкиваться и применять в минуты сомнений. В моем случае часть первоначальных принципов не прижилась и отвалилась, столкнувшись с реальностью, о них расскажу ниже. А вот те, которые остались:
  1. Большинство людей привыкли к стандартной раскладке в ОС Windows, впервые вышедшей на Vista (далее везде, PC-раскладка). В ней не все идеально, она не самая удобная, но уже прижилась. Поэтому для того, чтобы максимально быстро сделать рабочий инструмент я отталкивался от нее. А оригинальная раскладка, учитывающая реальную частоту употребления букв в языке, — это задача ближайшего будущего.
    image
  2. Совместимость дополнительных (типографских) знаков с английской раскладкой. Очень удобно, когда видишь на физической клавиатуре то, что можешь набрать. В русской раскладке многие знаки нашли себе место по остаточному принципу (и их меньше), поэтому на нее стараемся не ориентироваться (это касается только дополнительных знаков).
  3. Цифровая клавиатура уходит под Option (Alt). Да, на первый взгляд, это весьма сомнительное решение. Но другого выбора нет, потому что буквы используются намного чаще.
  4. Важно, чтобы с помощью башкирской раскладки можно было набирать тексты на русском, не переключаясь.

Проектирование

Прежде чем начать работу в редакторе, нужно перечислить и нарисовать все состояния, в которых может находиться клавиатура. Состояния эти зависят от нажатия клавиш модификаторов, таких как Command (cmd), Shift (?), Control (ctrl), Option (alt) и Caps Lock. В случае с башкирской клавиатурой, у меня получились следующие состояния:

  1. Башкирский алфавит строчные + основные знаки пунктуации — это стандартное состояние, по умолчанию;
  2. Башкирский прописные + основные знаки пунктуации — Caps Lock;
  3. Буквы алфавита прописные + основные знаки пунктуации 2 — Shift;
  4. Английский qwerty строчные (для команд и горячих клавиш, идентично английской раскладке) — Сommand;
  5. Английский QWERTY прописные (идентично английской раскладке) — Command + Shift;
  6. Дополнительные символы + цифры — Option;
  7. Дополнительные символы 2 — Option + Shift;
  8. Дополнительные символы (идентично английской раскладке) — Control.
Честно сказать, в ходе работы я постоянно экспериментировал и состояния менялись, добавлялись и убирались. Например, пробовал оставить цифры только в состоянии с нажатым Command, но при тесте это не работало, текстовый редактор не хотел набирать текст и ждал от пользователя команду. В конце-концов победили простые и привычные решения.

в редакторе

Для создания раскладки я пользовался бесплатной программой Ukelele, выпущенной сообществом SIL, которое известно, например, тем, что разрабатывает хорошие свободные шрифты и языковое ПО.

За основу был взят файл существующей русской раскладки ЙЦУКЕН. Есть 2 способа сделать это: первый — выбрать русский как источник ввода ОС, затем в программе открыть в меню File — New From Current Input Source (то есть, новый из текущего источника ввода); второй, открыть файл раскладки, идущий вместе с программой System Keybords/Cyrillic/Russian.keylayout
Вся работа происходит в визуальном редакторе, это просто и удобно. Чтобы назначить клавише знак, нужно сделать двойной клик по кнопке виртуальной клавиатуры. Чтобы редактировать состояние раскладки со влюченным модификатором, нужно просто нажать на клавишу модификатор, вместо стандартного состояния появится состояние, соответствующее модификатору. Чтобы не мучиться постоянно держа нажатой клавиши, включите залипание в Меню — View — Sticky Modifiers.
Обзор всех созданных состояний можно открыть с помощью command+shift+m (на приведенном снимке экрана, нумерация не соответствует той, что я задал в начале). Внизу отдельно указано, какое из состояний является стандартным (default set). В таблице мы видим, какие модификаторы используются для каждого состояния.



Возможно, вам потребуется создать какое-то состояние самому. Для этого нажмите «+», и выберите какие модификаторы задействовать. Заметим, что для клавиш Shift, Option и Control можно назначать правую или левую клавишу отдельно. У меня состояния получились схожими с теми, которые есть в русской раскладке.



После этого, нужно выбрать какой набор символов вы будете использовать.
  • Если вы выберете Empty, откроется чистая раскладка без символов.
  • Standart можно открыть какой-то из распространенных наборов, например английскую QWERTY.
  • А если нужно выбрать существующий набор, выбираем пункт Copy of existing map.
Apple выпустила более десятка различных видов клавиатур, различающихся расположением клавиш и стандартами. Поэтому, нужно обязательно постоянно тестировать раскладку. Список всех клавиатур открывается в Меню — View — Keyboard Types.



Обратите особое внимание на различие типов ANSI и ISO, во втором клавиш больше. Например, у меня возникла проблема, что в современных Apple Wireless ISO клавиатурах на месте клавиши «`» в рядом с цифрами располагается клавиша «>», и когда когда у пользователя ANSI клавиатура, буква? внезапно пропадала. При этом, если перенести ее на клавишу «`», на ISO она была бы не в ряду цифр, а по соседству с Я в 4-м ряду. В итоге, пока мне пришлось оставить букву? на обоих клавишах.



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



Итоговая схема раскладки

Из-за отличий в конфигурациях физической клавиатуры Мака, не удалось сохранить верхний ряд с дополнительными дополнительными буквами башкирского алфавита точно таким же как в PC-раскладке. Например, «?» переместилась на место «№», потому что «№» точно не является часто используемым знаком. Хотел бы я спросить авторов первоначальной раскладки, как он туда вообще попал. Место двоеточия заняла запятая, потому что она нужна гораздо чаще и отмечаная на физической клавиатуре. При нажатии Shift место запятой занимает точка с запятой, а точки — двоеточие, довольно легко запомнить.



С состояниями при нажатом Option и Option+Shift я «игрался» в пятнашки дольше всего. Но помогли мне разобраться несколько правил. На Option переехали все цифры и знаки верхнего ряда (+ часть типографских знаков изображенных на физической клавиатуре) из стандартного состояния английской раскладки, а на Option+Shift из нее же состояние с Shift. Максимально старался использовать мнемонические , например № находится на клавише N, а знак евро на клавише с латинской E.



Состояния при нажатых Command, а также Command+Shift, как и планировалось, полностью соответствуют стандартной английской раскладке, с Shift+ Control — английской Control. Это необходимо, чтобы в системе и приложениях работали горячие клавиши и навигация с клавиатуры.



Добавление иконки

Для начала, нужно в графическом редакторе создать уменьшенную копию флага, соответствующего языку, размером 16x12 px (или 16x11 px в зависимости от того, что на рисовано на флаге) и сохранить в формате PNG.



Переконвертировать все это в родной формат маковских иконок .icns можно при помощи программы fasticms. После запуска программы на экране появится куб, куда перетаскиваем файл png и сохраняем его как icns в открывшемся окне.



Чтобы прикрепить иконку к раскладке пройдите в Меню — Keyboard — Attach Icon File.

Установка дополнительных параметров

Осталось сделать еще несколько действий и прежде чем опубликовать раскладку.

Нужно добавить название раскладки, которое будет отображаться в системе (Меню—Keyboard—Set Keyboard Name). Примеры названий: ArmenianWesternQWERTY, Serbian-Latin и Turkish-QWERTY-PC. Я назвал свою версию Bashkir-PC.

Теперь нужно установить язык, письменность, регион и вариант письменности (Меню—Keyboard—Set Keyboard Name). В башкирском языке используется кириллица.



Не забывайте контролировать версии вашей раскладки (Меню—Keyboard—Set Version Info).

Ну все, теперь можно сохранить файлы и пользоваться. Обратите внимание, что вместе с основным файлом раскладки в формате keylayout рядом обязательно должен быть файл иконки в icns c аналогичным названием.



Вы можете скачать и установить себе созданную башкирскую раскладку.
Инструкция по установке есть на странице проекта.

Дополнительные материалы по теме

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

Киргизская раскладка

Еще одна инструкция по созданию раскладки в Ukelele

Можно почитать учебные материалы, которые идут в комплекте с программой (папка Ukelele Tutorial).

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Фраза «перезалил на habrastorage» теряет смысл

Пока разработчики сайта скромно молчат, занятые тестированием новой функциональности, сообщу о незаметном, но важном деле размножения интернетов на отдельном сайте. Об этом уже писали на Хабре 10 дней назад: habrahabr.ru/post/188436/, но более явно пояснить нововведение заставила фраза в одной из свежих статей: "перезалил на habrastorage". Всё было бы хорошо, но теперь в этом нет смысла.

Если раньше годами сайт Хабра пользовался сторонними сервисами показа изображений, в связи с чем изображения умерших сервисов искажали вид и иногда смысл старых статей, сейчас дошли руки и возможности до того, чтобы сайту уже не зависеть от произвола случайных хостингов — все изображения роботы автоматически переписывают на habrastorage.org. Над комментариями эта незаметная началась раньше, в июле, над содержанием статей — недавно, в начале августа (2013). Примеров даже приводить не надо — посмотрите исходный код HTML любых недавних статей — в них вы уже не найдёте доменов с «левыми» картинками. Или лучше посмотрите на код, где автор достоверно пользовался сторонним хостингом картинок: habrahabr.ru/post/189474/, потому что большая часть авторов добровольно пользуется habrastorage.org.

Вот случай, когда автор озаботился записью рисунков на habrastorage.org:



А здесь случай, когда автор статьи пользовался привычным сторонним сервисом (уже неважно и неизвестно каким):



Разница — в том, что робот добавил автосохранённую картинку не в основной домен habrastorage.org, а в поддомен habr.habrastorage.org. И это всё, что осталось от былой связности и анархии интернета.

Старые статьи (июль и раньше) не подвергаются изменениям роботом.

Результат нововведения для пользователей имеет значительно больше плюсов, чем минусов. Теперь картинки не зависят от произвола сторонних сервисов, но автор, как и раньше, при редактировании статьи может изменить картинку на обновлённую (робот после редактирования снова немедленно запишет её в кеш habrastorage.org).

Есть и другие плюсы. Минус видится в двух моментах: автор не может манипулировать картинкой прямо со своего хостинга и 2) — автор не может ставить счётчики и публиковать статьи со статистикой посещений, как ещё недавно было можно делать здесь: habrahabr.ru/post/186864/. Это — почти последняя статья о статистике посещений страниц (с графиками).

Такой минус, описанный в прежней статье — тоже не минус и легко решается ссылкой:
Употребление внешних картинок делало возможным размещение в конце блогозаписи кнопки-картинки, совмещённой со счётчиком нажатий её. Что-то вроде «Твитнуть! — 150 человек твитнуло». (Или со счётчиком какого-нибудь другого количества. Например, «Пожертвовать деньги на вышеописанный проект! — 320 050 рублей ужe собрано».) Теперь картинка перестанет меняться, так что такой приём делается не возможным на ?? е.
Потому что, во-первых, клик по простой картинке и раньше ничего не делал, а эффект счётчика можно было бы достичь только ссылкой, по которой откроется другая картинка-счётчик. Но и сейчас — пишем ссылку, открывающую страницу на другом сайте со счётчиком — получаем тот же самый счётчик.

Вывод: можно постить картинки теперь куда угодно, лишь бы они хотя бы раз прочитались. Например, на свой Дропбокс. После нескольких секунд демонстрации робот сам сохранит рисунки из статьи на сайте Хабра, а дропбокс- или амазон-хостинг будет защищён от хабраэффекта и избыточной траты денег на траффик для автора (владельца хостинга с платой за траффик). (Вопрос качественности, ужатия картинок — не исследовался, но приведу цитату ответа Boomburum по этому поводу:

2) Допустимый размер загружаемого изображения был увеличен с 800х1000 до 1920х1200 (а может и больше по высоте, не помню) — этого вполне хватит, чтобы залить даже самый крупный скриншот, с 24"-моников. Кто-то спросит «а как же ретина» и будет прав, но надо понимать, что мы делаем не фотохостинг для полноразмерных фотографий.
Картинки более высокого разрешения теперь надо будет показывать только ссылками или, например, ссылками с картинками с предпросмотром. При этом сайт с помощью робота будет сам делать среднекачественное превью, примерно до размера 1000 пикс. в ширину.)
Пример того, как публиковать картинки высокого разрешения:
<code class="html"><a href="моя_ссылка_на большую картинку"><img src="та_же_самая_моя_ссылка_на большую картинку"/></a>
</code>
Вторая ссылка подменится, первая — нет.

P.S.: на сторонние ресурсы страниц ещё не подменяются на сохранённые копии.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Летняя школа по биоинформатике

image

В этом посте, дорогой читатель, я кратко расскажу о том, как 100+ человек могут с пользой для знаний весело провести неделю лета.
Я постарался описать событие так, чтобы даже человек, находящийся совершенно не в теме, о чем идет речь, все равно бы прочитал с интересом и все понял.
В общем, это пост о нашей школе по биоинформатике, проходившей с 29 июля по 4 августа под Москвой. За подробностями — под кат.
Осторожно, траффик, все фото без катов!

image
Участники, организаторы и некоторые спикеры школы.

Введение

Итак, примерно в апреле Институт биоинформатики начал прием заявок на конкурсный отбор в летнюю школу. Заявлялось, что это будет недельное обучение различным дисциплинам в области биоинформатики, проходящее где-то под Москвой с оплатой проживания.
Тут надо сказать, и я полагаю, что это будет интересно читателю, который пока что чувствует себя «не в теме», что на описываемый мной момент, с биоинформатикой меня связывал только пройденный курс «Алгоритмы в биоинформатике» в Computer Science клубе. К слову, и на этот курс я тоже попал практически случайно, просто захотелось послушать что-то новое.
Сам я родом из Санкт-Петербургского Технологического института, с факультета Информационных технологий и управления, разрабатываю ПО, в основном на С++ и С++ Qt. В общем, как видите, самый обычный технарь. Никаких знакомств у меня в биоинформатике не было, кроме дальнего, на тот момент, товарища, который это все посетить и посоветовал.
Я подал заявку, и в июле меня оповестили о том, что я принят и что мне, как и всем участникам, будет оплачен трансфер от МГУ до пансионата, где все будет проходить, и обратно, а так же проживание и питание.

Школа

Первый день отличался от всех других в первую очередь тем, что занятия проходили на кафедре биологии МГУ. Мне пришлось приехать за день, поэтому я провел ночь у подруги в квартире, окна которой как раз выходили на шпиль МГУ. Я был уверен, что находясь в области прямого зрительного контакта от нужной точки, я доберусь туда без труда. Однако, утром я был немного удивлен тем, что автобусы ездят не совсем очевидными для меня маршрутами вокруг, а большая часть москвичей не может внятно ответить, как добраться. Пропущу долгое повествование, наполненное нецензурной лексикой, и скажу лишь, что до места встречи я добрался лишь благодаря встреченным по пути другим участникам.

Кстати, об участниках, по условиям набора, подать заявку мог любой желающий, но предпочтение отдавалось IT-шникам и биологам. Эта двоякость была отображена как в самой организации школы: участники были разбиты по потокам, биологи и информатики соответственно, так и в символике: на футболках, выданных каждому, были изображены цветок и компьютер. Правда насчет того, компьютер ли это, мы все так и не определились. Были варианты, как: мироволновка, печка, теливизор, окно MacOS и т.д. Другие варианты можно предложить в комментариях :)

imageimage
Вентилятор и печка с вытяжкой Цветок и компьютер.

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

Перед аудиторией на факультете биологии в МГУ, помимо футболок, нам выдали бейджик, блокнотик, ручку и прочую атрибуцию спонсоров школы, а так же расписание. Можно обратить внимание на то, что занятия у потоков иногда разные.
В первый день было сразу же интересно и мало совсем уж непонятного (чего я и боялся), особенно заинтересовала лекция «Генетическое репрограммирование соматических клеток: что нам даёт биоинформатика» о стволовых клетках. Я буду упоминать по ходу статьи только некоторые лекции без особого описания их содержания, потому, что все видеозаписи будут доступны в ближайшее время на этой странице, и если вас что-то заинтересует — вы сможете просмотреть лекцию.
После всех выступлений мы отправились в пансионат около Менделеево. По пути осознал насколько плохо жить в Москве — часовую дорогу мы ехали 2.5 часа.

image
Место жительства и обучения.

В пансионате было все нужное для обучения — интернет (хоть и постоянно падающий от нагрузки), аудитории, доски, розетки.
Занимались мы много, зачастую с 10 до 7 вечера, иногда и больше. Но если человек устал — никто не мешал ему прогуляться по природе вместо занятия или поспать.
Порадовал еще следующий организационный момент: так называемые «кофе-брейки» — перерывы на кофе между лекциями, где кроме самого кофе всгеда был чай и печеньки или другие плюшки.

image
Кофе-брейк

Второй день был тоже довольно простым, все было понятно даже непосвященному человеку, рассказали (информатикам, у биологов было параллельно что-то другое) об основах микробиологии, строении клетки, органеллах и т.д. Так же было небольшое задание с юнит-тестами и пайплайном на питоне.
Вечером было занятие-игра со сборкой генома. Суть в следующем: вам выдают много листков с ридами и ваша команда должна как можно быстрее собрать их и записать полученный геном. Кто справится быстрее и качественнее всех — того и тапки. Наша команда победила :) Игра полезная тем, что если кто-то еще не понял, что такое сборка генома, то по ней точно наглядно поймет. Ну и, она просто веселая.

image
Наша команда с призом.

image
Еще одна хорошая команда :)

image
Правильный ответ.

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

Честно говоря, не помню с какого дня, но довольно скоро стали входить в традицию ночные, а у кого-то даже доутренние тусовки. Они включали в себя социальные и настольные игры: Шляпа, Мафия, Эволюция, ну а у кого-то и употребление спиртосодержащих напитков. Участвовали в таких общественных инициативах не все, но большинство. Был забавный момент, когда из скудных запасов спиртного был организован мини-бар около играющих. Я думаю, эта веселая фича запомнилась всем, кто там был :)

image
Мини-бар на заднем фоне во время игры.

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

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

А потом мы фотографировались (первое фото в посте), много фотографировались :) Есть даже гифка. После группового фото была еще пара лекций, а потом прощальный вечер, с едой и напитками, любезно предоставленными организаторами, общением, играми и даже танцами. За последнее ответственен товарищ Андрей Афанасьев, спикер, подогнавший автомобиль с колонками :) В общем, для полной ламповости вечера (а у кого-то и ночи, перетекшей в утро) не хватало только костерка с историями. В любом случае, расставаться было неприятно, только свыклись друг с другом.

Заключение

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

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

image
Сертификат участника школы.

Послесловие

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

image

Скрытый текстОрганизаторам:
А так же учебным заведениям:
И спонсорам:

И, конечно, всем спикерам, а так же нам, участникам.

Для участников
Спасибо за эту классную неделю, все вышло очень тепло и по-дружески. Мне не хватает ночных посиделок в коридоре.
Не разбегайтесь, а то оно как обычно бывает, в друзья в ВК добавили друг друга и забыли. Так не пойдет :)

Для хабровчан и просто читателей которые живут в Санкт-Петербурге
Институт биоинформатики продолжает набор студентов на программы Алгоритмическая биоинформатика и Биоинформатика для биологов.

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

Всем науки, пока.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Rhodecode 2.0 Enterprise

Вышла новая версия RhodeCode — веб-интерфейса к Mercurial и Git, «конкурента» gitlab, gitolite и других «self-hosted github» систем. Changelog для версии 2.0 не такой уж большой, пожалуй, самое значительное — немного измененный внешний вид:



Зато кардинально изменилась модель распространения, которая теперь направлена на более активную монетизацию.

Пользователям на выбор предлагают следующие лицензии:

  • Startup (до 20 пользователей, без поддержки, free).
  • Business (до 50 пользователей, с поддержкой, $49/месяц).
  • Enterprise (неограниченное количество пользователей, с поддержкой, $299/месяц).
  • Лицензия для образовательных учреждений, OpenSource-проектов и некоммерческих организаций по защите прав человека (неограниченное количество пользователей, free).

У доступных пока вариантов лицензии есть несколько минусов:

  • Минимальный срок, на который можно приобрести лицензию — год.
  • В случае, если лицензия истекла, количество пользователей будет ограничено 20.

В будущем список лицензий будет расширен (возможно, в следующем году появятся версии без ограничения на количество пользователей и без поддержки).
Ядро RhodeCode (весь python код и HTML-файлы) по прежнему доступно под лицензией GPL, все остальные файлы (включая, но не ограничиваясь, CSS и изображениями) — под более ограниченной лицензией (по условиям которой, однако, после 1 августа 2015 года все ресурсы будут распространяться под GPL).
Последняя «не-Enterprise» версия RhodeCode, которая вскоре будет доступна на pypi.python.org — 1.7.2. Начиная с версии 2.0 развиваться будет только Enterprise версия.



Как вы относитесь к такой модели лицензирования?


Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста. Проголосовал 151 человек. Воздержалось 44 человека.


Положительно: фирмы с 20+ разработчиками вполне могут себе позволить заплатить $49/месяц



Отрицательно: определенно следовало предусмотреть бесплатную версию без поддержки и без ограничений на количество пользователей


Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[recovery mode] Еще один способ управления вентилятором в Linux (на примере Acer S3-391)

Понадобился мне однажды для работы ноутбук. Уж не помню почему, но выбор пал на Acer S3-391, тонкий, легкий, быстрый, но не лишенный недостатков. Кроме плохого экрана (который кстати не так просто заменить — у него особый коннектор, и возможно он приклеен к рамке), особенно меня раздражал шум вентилятора.
Пути решения этой проблемы я и постараюсь осветить в этой статье.

Прочитав статью Управляем вентилятором ноутбука через DSDT в Linux и не только, как и автор, я начал усердно гуглить в сторону ACPI и DSDT, даже перекомпилировал и подключил свою таблицу, но найти «ту самую» строчку кода отвечающую за работу вентилятора так и не удалось.



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

Как обстоят дела в Win
Для ОС от Майкрософт написано очень много программ для управлени вентилятором, все он по большей части заточены в лучшем случае под одного производителя. Что наводило на неприятные мысли.
Но тем не менее была найдена относительно универсальная программа NBFC, которая сразу заработала, требовалось лишь выставить тригеры переключения оборотов.

Какое-то время решение меня устраивало, но на душе все равно было как-то неспокойно.

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

Решение было не то что бы совсем на поверхноости, но точно не глубоко. Точнее в мануале приложенном к софтине.

Было найдено «правильное слово» по которому нужно гуглить: Embedded Controller (EC).

как написано на rom.by
Embedded Contoller — это встроенный контроллер типа Hitachi H8 (он же — Renesas), Winbond W83L950D, предназначенный для управления платформой (как правило — мобильной) как на уровне включения и выключения, так и для обработки ACPI-событий. В задачи EC-контроллера входит обслуживание аккумулятора мобильной платформы: выбор режима его заряда, контроль разрядки. Как правило, на мобильных платформах с помощью EC-контроллера реализуется и контроллер клавиатуры.

Оказалось что состояние вентилятора так же записывается в регистры этого контроллера.
Отавалось решить 2 задачи:
1) Какие регистры отвечают за состояние вентилятора
2) Как изменять их значение

Решение
С первой задачей помогла справится все также программка NBFC. Всего-то и нужно было посмотреть значения в конфиге для своего ноутбука (ультрабука?)
А с задачей «Как?» помог справится скрипт на перле шестилетней давности, который заработал сразу и без правок.

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

Собственно сами скрипты:

Переработаный под мои нужды скрипт управления
<code class="perl">!/usr/bin/perl -w

# Copyright © 2013 George Butskivsky	butskivsky (at) gmail.com
#
# Version 0.1 (09-aug-2013)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.


require 5.004;

use strict;
use Fcntl;
use POSIX;
use File::Basename;

my $fan_control_reg = 0x93;
my $fan_manual_mode = 0x14;
my $fan_auto_mode = 0x04;
my $fan_speed_reg = 0x94;
my $fan_speed_val_10 = 0xe6; # 10% of power
my $fan_speed_val_20 = 0xc8;
my $fan_speed_val_40 = 0x96;
my $fan_speed_val_50 = 0x7e;
my $fan_speed_val_60 = 0x64;
my $fan_speed_val_80 = 0x32;

sub initialize_ioports
{
  sysopen (IOPORTS, "/dev/port", O_RDWR)
    or die "/dev/port: $!\n";
  binmode IOPORTS;
}

sub close_ioports
{
  close (IOPORTS)
    or print "Warning: $!\n";
}

sub inb
{
  my ($res,$nrchars);
  sysseek IOPORTS, $_[0], 0 or return -1;
  $nrchars = sysread IOPORTS, $res, 1;
  return -1 if not defined $nrchars or $nrchars != 1;
  $res = unpack "C",$res ;
  return $res;
}

# $_[0]: value to write
# $_[1]: port to write
# Returns: -1 on failure, 0 on success.
sub outb
{
  if ($_[0] > 0xff)
  {
    my ($package, $filename, $line, $sub) = caller(1);
    print "\n*** Called outb with value=$_[1] from line $line\n",
          "*** (in $sub). PLEASE REPORT!\n",
          "*** Terminating.\n";
    exit(-1);
  }
  my $towrite = pack "C", $_[0];
  sysseek IOPORTS, $_[1], 0 or return -1;
  my $nrchars = syswrite IOPORTS, $towrite, 1;
  return -1 if not defined $nrchars or $nrchars != 1;
  return 0;
}

sub wait_write
{
	my $i = 0;
	while ((inb($_[0]) & 0x02) && ($i < 10000)) {
		sleep(0.01);
		$i++;
	}
	return -($i == 10000);
}

sub wait_read
{
	my $i = 0;
	while (!(inb($_[0]) & 0x01) && ($i < 10000)) {
		sleep(0.01);
		$i++;
	}
	return -($i == 10000);
}

sub wait_write_ec
{
	wait_write(0x66);
}

sub wait_read_ec
{
	wait_read(0x66);
}

sub send_ec
{
	if (!wait_write_ec()) { outb($_[0], 0x66); }
	if (!wait_write_ec()) { outb($_[1], 0x62); }
}

sub write_ec
{
	if (!wait_write_ec()) { outb(0x81, 0x66 ); }
	if (!wait_write_ec()) { outb($_[0], 0x62); }
	if (!wait_write_ec()) { outb($_[1], 0x62); }
}

sub read_ec
{
	if (!wait_write_ec()) { outb(0x80, 0x66 ); }
	if (!wait_write_ec()) { outb($_[0], 0x62); }
	if (!wait_read_ec())  { inb(0x62); }
}

sub print_regs
{
	initialize_ioports();

	my @arr = ("00","10","20","30","40","50","60","70","80","90","A0","B0","C0","D0","E0","F0", "");

	my $i = 0;
	my $t = 0;
	print "\n  \t00\t01\t02\t03\t04\t05\t06\t07\t|\t08\t09\t0A\t0B\t0C\t0D\t0E\t0F\n";
	print "  \t__\t__\t__\t__\t__\t__\t__\t__\t|\t__\t__\t__\t__\t__\t__\t__\t__\n";
	print "00 |\t";
	for ($i = 0; $i < 256; $i++)
	{
		$t = read_ec($i);
		print $t;
		print "\t";
		if ((($i + 1) % 8) == 0){
			if ((($i + 1) % 16) == 0) {
				if ($i != 255) { print "\n$arr[(($i-(($i + 1) % 16)) / 16) + 1] |\t"; }
			} else {
				print "|\t";
			}
		}
	}
	
	print "\n";
	
	close_ioports();
}


if (!$ARGV[0]){
        print "wrong arguments!\n";
	print "usage:\n";
	print "\'fan_control regs\' \t\t\t\tdumps all ec registers\n";
	print "\'fan_control ?= <reg>\' \t\tQuery register's value\n";
	print "\'fan_control := <reg> <val>\' \tSet register's value\n";
	print "\'fan_control 10|20|40|50|60|80\' \tSet fan speed value in percents\n";
	print "\'fan_control auto|manual\' \tSet fan policy\n";
	print "\'fan_control getspeed\' \tGet current speed fan value in dec format (255-0) lesser is louder\n";
} elsif ($ARGV[0] eq "regs") {
	print_regs();
} elsif ($ARGV[0] eq "?=") {
	initialize_ioports();
	my $r = hex($ARGV[1]);
	printf("REG[0x%02x] == 0x%02x\n", $r, read_ec($r));
	close_ioports();
} elsif ($ARGV[0] eq ":=") {
	initialize_ioports();
	my $r = hex($ARGV[1]);
	my $f = hex($ARGV[2]);
	my $val = read_ec($r);
	printf("REG[0x%02x] == 0x%02x\n", $r, $val);
	printf("REG[0x%02x] := 0x%02x\n", $r, $f);
        write_ec( $r, $f);
	printf("REG[0x%02x] == 0x%02x\n", $r, read_ec($r));
	close_ioports();
} elsif ($ARGV[0] eq "10") {
	initialize_ioports();
	write_ec( $fan_speed_reg, $fan_speed_val_10);
	close_ioports();
} elsif ($ARGV[0] eq "20") {
	initialize_ioports();
	write_ec( $fan_speed_reg, $fan_speed_val_20);
	close_ioports();
} elsif ($ARGV[0] eq "40") {
	initialize_ioports();
	write_ec( $fan_speed_reg, $fan_speed_val_40);
	close_ioports();
} elsif ($ARGV[0] eq "50") {
	initialize_ioports();
	write_ec( $fan_speed_reg, $fan_speed_val_50);
	close_ioports();
} elsif ($ARGV[0] eq "60") {
	initialize_ioports();
	write_ec( $fan_speed_reg, $fan_speed_val_60);
	close_ioports();
} elsif ($ARGV[0] eq "80") {
	initialize_ioports();
	write_ec( $fan_speed_reg, $fan_speed_val_80);
	close_ioports();
} elsif ($ARGV[0] eq "manual") {
	initialize_ioports();
	write_ec( $fan_control_reg, $fan_manual_mode);
	close_ioports();
} elsif ($ARGV[0] eq "auto") {
	initialize_ioports();
	#write_ec( 0x93, 0x04);
	write_ec( $fan_control_reg, $fan_auto_mode);
	close_ioports();
} elsif ($ARGV[0] eq "getspeed") {
	initialize_ioports();
	my $speed = read_ec($fan_speed_reg);
	my $dec_speed = sprintf("%d", $speed);
	printf("fan speed == %d\n", $dec_speed);
	close_ioports();
} else {
	print "wrong arguments!\n";
}	

</code>


Логика работы програмы
<code class="perl">#!/usr/bin/perl -w

$temp = `cat /sys/class/thermal/thermal_zone0/temp`;
$silent = int(60000);
$half = int(65000);
$full = int(75000);


if ($temp < $silent) {
	system("/usr/bin/perl -w /usr/local/bin/fan_control.pl 20");
} elsif ($temp < $half) {
	system("/usr/bin/perl -w /usr/local/bin/fan_control.pl 40");
} elsif ($temp < $full) {
	system("/usr/bin/perl -w /usr/local/bin/fan_control.pl 80");
} else {
       	system("/usr/bin/perl -w /usr/local/bin/fan_control.pl auto");
}

</code>


Ляунчер
<code class="bash">#!/usr/bin/bash

/usr/local/bin/fan_control.pl manual
while [ true ]
do
	/usr/local/bin/fan_control_logic.pl
	sleep 5
done

</code>


Просто скопируйте в /usr/local/bin/ и дайте права на выполнение

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

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

<code class="bash">watch -n 1 sudo fan_control.pl regs
</code>

Если регистры, и их значения подобраны верно просто выполняем в консоли:

<code class="bash">sudo fan_control
</code>
вентилятор должен изменить обороты.
Profit!

Спасибо за внимание, надеюсь материал будет кому-нибудь полезен.
Критика, дополнения и улучшения приветствуются.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


mySQLgame 2.0

Устали от однообразных браузерных игр, которые представляют собой лишь набор кнопок, отправляющих запросы к базам данным? Встречайте Lone lord — игру, в которой нет кнопок и в которой надо писать запросы в базу данных.




Посылая определенные запросы в формате, похожем на синтаксис MongoDB, вы можете: строить и апгрейдить замки и башни, добывать бриллианты и дерево, нападать на соседей, торговать на рынках, обменивать ресурсы в Государственном банке Lone lord, объединяться с другими игроками в клики и воевать в масштабных феодальных войнах!

Несмотря на заголовок, игра не является продолжением mySQLgame, но является ее закономерным эволюционным развитием: в отличие от “первой части”, в Lone lord есть торговля, и добыча ресурсов, объединение в клики и удобный игровой чат. А еще у нас есть боты.

Да, в отличие от большинства онлайн-игр, боты в Lone lord не запрещаются, а приветствуются! Всего за 10 бриллиантов вы получите верного слугу, помощника в торговле и добыче ресурсов, почтальона, руководителя игрового казино – возможности ботов ограничены только вашей фантазией и нестрогими правилами.

Не ждите, регистрируйтесь прямо сейчас и получите 2.5x бонус к стартовым ресурсам!

Технологии


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

Игра разрабатывалась ровно месяц под впечатлением от вышеупомянутой mySQLgame с желанием внести полезные улучшения и устранить фатальный недостаток.

И серверная, и клиентская части написаны на CoffeeScript, языке с похожим на Ruby синтаксисом, компилируемом в JavaScript. На сервере использовались Node.js с Engine.io для обработки запросов, JADE для верстки, Stylus для стилей. База данных – SQLite.

На клиенте вместо традциционной jQuery решил использовать Zepto.js, совместимой с первой на уровне синтаксиса. Размер минифицированного JS-файла у последней получился в 4 раза меньше, чем у более известной библиотеки, но потерялась поддержка всех версий IE. Говорят, можно ее как-то пропатчить и добавить поддержку IE9-10, но у меня не получалось это сделать.

Чат и лог в игре реализованы на веб-сокетах при помощи Engine.IO, так что о том, что на вас напали или то, что одна из ваших башен принесла долгожданный бриллиант, вы узнаете моментально. :)

Для парсинга запросов из командной строки использовал библиотеку, на которую случайно натолкнулся на Stack Overflow – jsonlite. Она позволяет писать JSON-запросы без кавычек везде, где это возможно, что очень удобно при наборе большого количества команд.

Игра
Игра (компактная версия)
Вики (с чего начать, синтаксис команд)

P.S. Будьте осторожны. Вполне возможно, что под всем этим скрывается действительно интересная игра…

P.P.S. Если у кого не приходят письма на E-mail, напишите мне в личку или на почту.

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


[Перевод] Интервью с Джульеном Данжу, руководителем проекта OpenStack Ceilometer

Мы представляем пятое из серии интервью с техническими руководителями проекта OpenStack в блоге Mirantis. Наша цель — обучить более широкое сообщество технических специалистов и помочь людям понять, как они могут внести вклад в проект OpenStack и извлечь из него выгоду. Естественно, ниже изложена точка зрения интервьюируемого, а не компании Mirantis.

Ниже мы представляем интервью Джульена Данжу (Julien Danjou), технического руководителя проекта OpenStack Ceilometer.

Mirantis: Расскажите о себе.

Джульен Данжу: Я фрилансер, свободный разработчик, участвую во многих проектах FOSS, а также в течение более чем десяти лет разработчик .

Вопрос: Какова ваша история взаимоотношений с OpenStack? Почему вы участвуете в проекте?

Ответ: Я начал работу на проекте OpenStack с компанией eNovance, которая взяла меня на работу в конце 2011 для создания первой европейской облачной платформы на основе OpenStack. В тот момент я не имел представления о том, что такое OpenStack, но над платформой IaaS с открытым кодом в Python была очень увлекательной, поэтому я присоединился. С того времени была создана целая экосистема OpenStack и возникают новые технические задачи; достаточно причин для того, чтобы принимать участие!

Вопрос: В чем отличие проекта OpenStack от других проектов с открытым кодом, в которых вы участвовали?

Ответ: Я бы назвал среди отличий прагматизм и хороший выбор технологий, что возможно является основными признаками успешного проекта с открытым кодом.

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

Вопрос: Какова ваша ответственность как технического руководителя проекта Ceilometer?

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

Вопрос: Вы можете объяснить роль Ceilometer в рамках проекта OpenStack? Чем так важен инструмент Ceilometer?

Ответ: Большинство людей, которые строят свою платформу IaaS, хотят выставлять счет за использование ресурсов платформы. На основе этого первого варианта использования мы определили роль Ceilometer в рамках OpenStack как место измерения платформы OpenStack. Затем уже область действия распространилась на более широкую коллекцию измерителей, реализующих множество различных вариантов, от биллинга до срабатывания тревожных сообщений.

Цель проекта Ceilometer – подсчитать все, что происходит в платформе OpenStack, чтобы выставить счет за это или иным способом провести анализ.

Вопрос: Что уникально в проекте, в чем прорыв проекта Ceilometer?

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

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

Вопрос: Чего достигло сообщество Ceilometer на данный момент?

Ответ: Мы построили проект с нуля, встраивая его в каждый компонент OpenStack без явного вмешательства. После того как накопились результаты работы, мы вступили в процесс инкубации, а затем вышли из него в качестве интегрированного проекта. И все это только за один год. Спустя всего лишь 6 месяцев разработки операторы OpenStack использовали Ceilometer для измерения своих платформ и выставления счетов или сбора средств за их использование, одновременно с генерацией гигабайтов данных измерений в день.

Вопрос: Какие возможности предоставит Ceilometer в выпуске OpenStack Havana?

Ответ: Я думаю, мы — один из проектов с наибольшим запланированным объемом реализации. На выпуск Havana наша основная цель – это функциональность сообщений о тревоге, которая позволяет пользователям и операторам порождать события на основе оценки результатов измерений. Кроме того, это станет краеугольным камнем для проекта Heat, который предоставит возможность автомасштабирования на основе этой функциональности Ceilometer и связанных с ней данных.

Мы также планируем и реализуем новые возможности измерения, например, измерение полосы пропускания сети в Quantum и планирование событий в Nova, а также улучшаем наш публичный API-интерфейс, чтобы позволить выполнять более тонкие запросы и получать более подробные срезы статистики.

Вопрос: Какие поставщики больше всего вкладываются и предоставляют плагины? Кого бы вы хотели видеть в роли разработчиков Ceilometer?

Ответ: Сейчас у нас нет внешних разработчиков, которые распространяют плагины для Ceilometer. Что хорошо, так это то, что все наши плагины — это ПО с открытым кодом, распространяемые вместе с Ceilometer. Все они являются частью базового кода, созданного разработчиками Ceilometer. Тем не менее, мы будем рады увидеть вклад в системы на других платформах, не только на OpenStack, например Ceph.

Вопрос: Есть ли у проекта Ceilometer до сих пор “детские болезни” – что-то, что нужно поменять?

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

Вопрос: Каковы типичные рекомендации по использованию?

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

Вопрос: Что вы хотите, чтобы люди знали о проекте (скрытые возможности/функционал)?

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

Вопрос: Есть ли всеобщие заблуждения в отношении Ceilometer?

Ответ: У нас были некоторые неправильные представления в начале проекта, когда люди ожидали от Ceilometer печати PDF-счетов или мониторинга своей платформы и звонка системному администратору при сбое. Теперь достаточно ясно, что мы – склад результатов измерений OpenStack и вы можете использовать его для построения любого приложения поверх него, в том числе для биллинга или активного мониторинга. Но мы не ставим целью предоставлять этот функционал.

Вопрос: Каковы необходимые предварительные условия?

Ответ: Нет необходимых аппаратных требований. Для программного обеспечения Ceilometer использует те же технологии (Python), что и остальные компоненты платформы OpenStack. Что касается знания технологий, вам определенно необходимо понимать глобальную архитектуру OpenStack, так как вам нужно подключить Ceilometer в каждый компонент!

Вопрос: Каковы требования для запуска Ceilometer?

Ответ: Для простой установки требуется работа инженера OpenStack на пару дней. Чем больше растут объемы использования и нагрузка, тем больше вам потребуется совершенствовать развертывание Ceilometer. Вот почему и как собственно начали работу на проекте некоторые из наших разработчиков.

Вопрос: Какой совет вы бы дали людям / корпорациям, которые сталкиваются с теми же задачами, которые были у вас в начале пути?.. когда у вас нет представления об OpenStack, но нужно вскочить в проект …

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

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

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

Вопрос: Кого бы вы хотели видеть в роли разработчиков Ceilometer?

Ответ: В проекте Ceilometer множество различных аспектов — от сбора данных до интерфейса REST API, который возвращает данные. Поэтому, в зависимости от того, в какую часть кто-нибудь хочет вложиться, это может быть человек, который реализует поддержку Ceilometer в своем “продукте” (например, платформа PaaS) или занимается анализом данных и помогает в создании интерфейса REST API.

Вопрос: Какие функции необходимо улучшить или проверить?

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

Что касается тестов, наблюдается большой пробел в плане драйверов хранения. Самый первый и наилучшим образом поддерживаемый — MongoDB, а драйверы хранения SQLAlchemy и HBase потребуют большего объема тестирования и возможно исправления.

Вопрос: Как именно люди могут начать работу?

Ответ: Я думаю, что как и в случае с большинством проектов OpenStack, самый простой способ начать работу и поиграть с Ceilometer — это использовать установку devstack. Ceilometer полностью интегрирован с devstack, поэтому его легко включить и развернуть вместе с Nova, Glance и т.п. После этого вы можете экспериментировать с инструментом Ceilometer – использовать или вносить свой вклад!

Вопрос: Большое спасибо, Джулиен.

Ответ: Не за что!

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


Методология разработка на 1С-Битрикс – опыт дурака

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

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

Исходные данные:

  • Есть интернет-магазин на 1С-Битрикс
  • Проекту несколько лет, но только несколько месяцев назад сайт перевели на 1С-Битрикс
  • Посещаемость 10-15 тыс. человек в день
  • Каталог магазина содержит около 12 000 позиций товаров
  • Простои и отключения сайта недопустимы
  • Проект в течении полугода разрабатывался другой компанией:
    1. Есть ТЗ, примерно на 100 листов, соответствующее выполненной работе примерно на 40%
    2. Никакой документации проекта

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


Разработкой программного обеспечения в целом, и web-проектов в частности, занимаюсь около 8 лет. За это время сталкивался с проектами различной сложности и, на первый взгляд, задаче не показалась мне слишком трудной. При выполнении проектов в нашей компании, как правило, применяется методология SCRUM. От нее я и начал отталкиваться.

Первым делом, получил доступ исходному коду проекта. Поверхностно проанализировал. Согласовал с заказчиком список первостепенных задач. Составил план разработки для 3х разработчиков и, как сказал Гагарин, поехали!

Проблема №1 – во всем виноваты разработчики

Как это обычно и бывает, во всем виноваты все, кроме заказчика. Дизайнер сделал макет, который слишком много весит, хостер предоставил сервер, который медленно работает, разработчики сделали сайт, который все время глючит и ломается, менеджеры выполнили какие-то задачи, которые мы выполнять не просили, после перехода со старой версии сайта на 1С-Битрикс произошло резкое снижение поискового трафика и т.д. Ситуация не однозначная. С одной стороны основная ответственность конечно же должна лежать на компании разработчике. Нужно было донести до заказчика последствия всех действий с сайтом и подготовить к результату. При выполнении работы предложить целостную архитектуру будущей системы и план разработки, которого нужно придерживаться до завершения основных этапов. Провести тщательное тестирование функционала и сдать работу. С другой стороны, не редко сталкиваюсь с ситуацией, когда заказчик все сам лучше знает, потому что у него мама когда-то рисовала, а посему является лучшим дизайнером, и его 7ми летний сын прекрасно разбирается в SEO-оптимизации, потому что все время проводит за компьютером, играя в GTA.

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

В результате:
  • Проект не доведен до логического завершения. Многие задачи брошены на середине пути
  • Проект не задокументирован. Работа части функционала не очевидна. При разработке нового функционала оказывается, что перестал работать функционал, который раньше работал и о существовании которого новый разработчик и не подозревал
  • Часть написанного предыдущим исполнителем кода приходится переписывать с нуля
  • Задуманная архитектура проекта в первые недели/месяца работы новому подрядчику не ясна. Доработка функционала одного модуля приводит к потере работоспособности функционала никак не связанного с ним модуля
  • Заказчик нервничает, исполнитель нервничает, посетители не довольны, посещаемость уменьшается, продажи падают

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

Проблема №2 – параллельная разработка.

В соответствии с лицензионной политикой 1С-Битрикс, каждая лицензия на сайт позволяет использовать 2 копии системы. Одну, как продакшен сайт, вторую – для разработки. Проблема заключается в том, что разработка ведется несколькими, в моем случае, тремя, разработчиками непрерывно. В случае с классической разработкой все просто. Каждый разработчик занимается своим модулем. Затем проводится функциональное тестирование каждого модуля, все доработки сливаются в репозиторий какой-нибудь системы контроля версий, дальше это тестируется все вместе (интеграционное тестирование). Если результат нормальный –тестовая версия презентуется заказчику. После принятия тестовой версии происходит продакшен-сервера. В соответствии с методологией SCRUM я определил, чтоб буду выкладывать новые версии на боевой сайт раз в неделю. Соответственно, есть 3-4 дня на основную разработку. 1 день на тестирование и исправление ошибок и пол дня на обновление боевого сервера. Сроки конечно колеблются, но «релиз каждый четверг» старался четко придерживаться.

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

Как же быть с лицензией? Обратился в техническую поддержку 1С-Битрикс. Получил предложение докупить доп. лицензии для разработки. Мягко сказать, не обрадовался, но других предложений не получил. Выход нашел достаточно быстро. Решил использовать NFR-ключи. Благо, партнерский статус позволяет. В результате создал 5 исталяций интернет-магазина:
  • Продакшен-сервер
  • Тестовый сервер
  • 3 сервера разработки (по одному на разработчика)

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

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

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

По мере построения схемы столкнулся с еще одной проблемой. Проект занимает на диске около 80Гб. Без кеша и временных файлов – около 60. Пытался по началу убрать картинки и видео из контроля версий – не получилось. Информация на сайте меняется постоянно. Тестировать нужно на актуальных данных. Первый комит сайта в репозиторий у меня шел кусками более 2х суток. Первый чекаут в папку для разработки проходит несколько часов (SVN сервер в локальной сети разработки). Если, не дай бог, случайно сделать полный апдейт папки проекта – можно уходить курить, обедать, играть в пинг-понг или керлинг. Комит толко выбранных файлов или папок проходит достаточно быстро. Решение: выполнил задачу – закомить сразу десяток измененных файлов.

Проблема №3 – обновление продакшен-сервера и совместная работа с заказчиком

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

Тут отлично работают законы Мерфи:
  • Если что-то плохо работает на тестовом сервере – на боевом сервере это обязательно сломается.
  • Если что-то отлично работает на тестовом сервере – на боевом сервере это все равно обязательно сломается.
  • Если баг на сайте существует всего 5 секунд, его обязательно найдет кто-то из посетителей и обязательно напишет об этом в отзывах или в форме обратной связи.
  • Если сайт не работает 1 минуту во время обновления, то именно в эту минуту владелец компании будет показывать его своему другу или конкуренту (и это не смотря на согласование времени и процедуры обновления).
Я, конечно, утрирую, но в каждой шутке есть доля шутки. Минимальная нагрузка на сайт с 4 до 6 утра. Обновлять в это время конечно бы лучше, но уж очень не хочется.

В случае большинства веб-приложений есть четкая структура разделения приложения на слои и обновление сайта можно разделить на 2 части:
  • Обновление программного кода
  • Обновление базы данных с помощью SQL-скриптов

В случае с 1С-Битрикс все немного сложнее. Во-первых, файлов много. У меня в проекте их более миллиона. Обычный апдейт из репозитория проходит никак не меньше 20-30 минут. Можно конечно апдейтить только измененный файлы, но тогда теряется весь смысл репозитория. Во-вторых, и это куда более печально, часто при апдейте приходится делать ручные изменения и настройки через админку. А это всегда медленно, нужно помнить все изменения, которые необходимо выполнить, велика вероятность случайно ошибиться. Можно, конечно, написать SQL скрипт, который сам внесет все нужные изменения в базу. В простейших случаях, разумеется, так и делаем. Но в большинстве случаев написание и отладка такого скрипта занимает больше времени чем сама разработка и намного больше времени, чем выполнение всех действий вручную с последующей проверкой.

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

Второе, с чем столкнулся, это совместная работа с заказчиком. Т.к. проект большой, над ним постоянно трудится около 30 человек. Контент-менеджеры, менеджеры по продажам, SEO-оптимизаторы, маркетологи и много еще кого. Естественно, каждый вносит в страницы сайта и настройку модулей какие-то изменения. Первым решением было забрать права у заказчика на внесение изменений в программный код сайта. Решение абсолютно правильно, но стало только хуже. Если раньше заказчик предполагал, что он так же может зайти на сайт и случайно что-то сломать, то теперь все шишки стали сыпаться только на нас. При чем. Даже если контент-менеджер криво отредактировал текст на странице и не закрыл какой-то тег – все равно виноват разработчик. Решение нашлось довольно простое. В маркетплейсе есть бесплатны модуль по контролю версий страниц. Проблему это не убрало, все равно кто-нибудь время от времени что-то да наплужит, но зато теперь появилась возможность посмотреть в любой момент времени кто менял, что менял и почему все сломалось. Результат, конечно, не ice, но кучу нервов мне экономит.

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

Проблема №4 – «сделайте мне срочно, это же задача на 5 минут»

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

Решение нашел только одно – никогда не идти на поводу у заказчика в ущерб надежности и безопасности. Как бы заказчик не просил, виноват всегда будет разработчик. Как говорил мне мой бывший начальник: «Я же тебя не просил сделать плохо».

И раз уж затронули тему бекапов, хочу заметить. Бекап средствами 1С-Битрик это конечно хорошо и удобно, но очень медленно. В случае, если срочно нужно восстановить 1-2 файла или несколько значений в базе, приходится ждать пока разархивируются все 60 Гб. Здесь наиболее эффективной мне кажется следующая схема:
  • Должен происходить ежесуточный бекап файлов и базы данных в виде архива на внешний источник данных.
  • Всегда делаем бекап непосредственно перед обновлением в одном из 2х вариантов:
    1. Вариант light – Копируем всю папку проекта в соседнюю папку на сервере. Базу данных в виде дампа сохраняем в отдельный файл. Ничего не архивируем. В случае, если нужно будет восстановить какое-то значение в базе или один из файлов, все будет под рукой и легкодоступно
    2. Вариант strong – аналогично предыдущему, только базу копируем в другую базу данных MySQL. Это позволит в случае полного краха за 1-2 минуты исправить в файле хостов корневую папку сайта и проект начнет работать из соседней папки с копией базы.


Заключение

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

Источник: habrahabr.ru,
получено с помощью rss-farm.ru


LSI Nytro MegaRAID NMR8100-4i в деле

Клиент сформулировал мне в HOSTKEY задачу — на 1 (один) сервер с 12 ядрами и 64Гб памяти надо примерно 3-4Тб места под более-менее однотипные виртуалки, но что бы работало все как на SSD и при этом уложиться в 16000р в месяц. Стали думать, вариантов было несколько:
  • делаем все на SSD. берем 6 дисков по 500Гб типа Samsung 840 Pro eMLC, собираем их в страйп или еще как хитро, добавляем пару дисков по 3Тб для бакапа и… не проходим в бюджет. 2U сервер, 8 портовый RAID контроллер и диски по 12000р за штуку не пропускают.
  • Делаем все на жестких дисках, берем 12x300Gb SAS 15K и опять не проходим ни в бюджет, ни в производительность.
  • Используем RAID контроллер с внешним SSD кэшем – LSI CacheCade или Adaptec MaxCache. Идея получше, но нам надо 4 диска по 2Тб в RAID10 – придется брать 8 портовый контроллер и к нему SSD на 120Гб eMLC или SLC. Что бы к SSD был доступ, опять надо брать 2U корпус. Контроллер 8 портов + SSD стоит около 37000р, в бюджет не проходим.
  • Используем новую LSI Nytro MegaRAID NMR8100-4i. Берем 1U систему, ставим в нее контроллер, ставим в нее 4 диска по 2Тб в RAID10 и вписываемся и в производительность и в бюджет. Нитра стоит 27000р, на ней уже стоят 2 диска по 44Гб, причем SLC!
Сказано – сделано, примерно 3 рабочих дня и 4 вариант у нас на столе. Посмотрим, на что он способен — не на рекламных проспектах, а на практике.



Машина в сборе:


1U Supermicro, 2xE5-2630 2,3GHz 12 ядер, 16Gb DDR3 ECC Reg LV х4=64Гб памяти (можно расширить до 256Гб при желании), LSI Nytro MegaRAID NMR8100-4i, 4x2Tb WDC RE 7200rpm HDD (WD2000FYYZ) SATA3. Все компоненты на 3-х летней гарантии.
Цена в месяц с размещением и 100М каналом – 16000р.



Спецификация нашей Нитры:


8xPCIe 3.0 (только Е5 и Е3), 4 порта SAS/SATA 6Gbps, два SSD SLC по 64Гб с резервированием 30% места, 1Гб кэша на DDR3, все возможные уровни RAID, поддержка экспандеров и можно поставить батарейку. Цена образца на момент августа 2013 года – 27000р, 3 года гарантии.
Кто хочет почитать полный обзор — внимание, много букв на английском.

Тесты

Посмотрим, на что способна наша Нитра. Смотреть будем под Виндой 2012 – наиболее наглядно. Сначала настроим в БИОС необходимые массивы и посмотрим настройки контроллера – все гибко настраивается самым традиционным образом. Внешний вид утилиты не менялся лет 15 наверно.



RAID

Отдельно настраивается RAID из пары встроенных SSD по 44Гб, отдельно логический том из остальных дисков. Можно сделать зеркало или страйп – выберем страйп, тем более что в документации явно написано, что если диск выйдет из строя, то система сама уберет его из дела. На логическом томе можно делать любой RAID – от 0 до 6. Все настраивается традиционно.



Готовый сетап




Загрузим Windows 2012 сервер, в комплекте с Нитрой идет флэшка с Megaraid Storage Manager – наконец-то. Ставим его, все видно из коробочки. Софт обычный, тоже не менялся лет 10. Все родное, на своих местах. Понятное поведение при авариях.



Очень важно, что теперь мы видим процент износа SSD и можем своевременно менять контроллер и принимать превентивные меры. На старых контроллерах если SSD был в массиве, то добиться от него SMART или еще чего-то было нереально.



Прогон блочного устройства

Собираем том на 4Тб — RAID10 и не размечая его подергаем HD Tune Pro для проверки сухой производительности, без помощи ОС и ее кэшей.

Чтение:





Прогон по чтению на всю емкость диска дает ожидаемый результат – 200-250Мб в секунду, около 100 IOPS, 10мс. В кэше явно пусто – все идет с диска. Маловато для 10 RAID, должно быть погуще. Но у нас другая задача, виртуализация. Производительность по чтению обычно нивелируется кэшами ОС.


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

Запись:





вот тут что надо, в среднем 266Мб/с и доступ 0,17мс. Нитра пишет в SSD и потом из него крупными блоками на диски. В начале забился 1Гб памяти контроллера, потом 3Тб системе хватало запасу по SSD и только последний 1 Тб писался уже прямиком на диски без кэша, диски не успевали.

Посмотрим что с записью – вот тут все шикарно. В одну очередь мы видим штатную производительность SSD – все записи идут через него, диски не участвуют.



Мы имеем 14000 IOPS на мелких блоках с типичным времени доступа 0,07 мс.