суббота, 10 декабря 2011 г.

Волшебные слова для разработчиков! :-)

Обычно я пишу сюда на тех. темы, но сегодня сделаю небольшое исключение.

Прочел в Твиттере новость (9 декабря 2011), что GSC Game World (разработчик "Казаков" и "Сталкера") закрывается. Там же по ссылке меня ожидал комментарий, содержащий (дословно):

"НО, отпилите себе ноги, отдавите себе яйца,выкиньте в окно тещу и сварите свою кошку ЧТОБЫ НИ ЧТО НЕ ПОМЕШАЛО ВЫПУСТИТЬ СТАЛЫЧА В СРОК!!"

Однозначно в закладки :D

среда, 26 октября 2011 г.

NuGet: Enable-PackageRestore

Если Вы пользуетесь NuGet для легкого управления зависимостями, то коммитить бинарники сторонних библиотек (они же пакеты) не обязательно. При экспорте/чекауте/пулле, получив свежие исходники, просто введите Enable-PackageRestore в командной строке менеджера управления пакетами (при этом уже должен быть установлен пакет NuGetPowerTools, если нет, установите его обычным образом с помощью NuGet) и он будет подтягивать нужные пакеты сам в случае их отсутствия (не забудьте закоммитить/запушить папку .nuget). Очень удобно!

понедельник, 12 сентября 2011 г.

Учебные проекты должны быть полезными - Learn Them All!

На выходных потянуло потренироваться с Python и Google App Engine. Но писать бессмыслицу не хотелось, к тому же давно планировал сделать удобное (по крайней мере для себя) и самое главное максимально простое (с точки зрения пользователя) облачное приложение, позволяющее заносить в список неизвестные слова иностранного языка и учить их, используя, например "Мозаику" (дальше пример).

Вот это приложение - Learn Them All:


Единственное на данный момент упражнение - это "Мозаика":


Принцип прост - входим с помощью аккаунта Google (у каждого пользователя - свои слова), добавляем слова, затем переходим к упражнению. Верный ответ (правильно сопоставлена пара) - это +1 к счету для данного слова, иначе -1. Когда счет больше 5, слово уже не появляется в упражнении. Слова можно редактировать (включая счет для данного слова). Также из списка слов можно перейти на страницу Лингво.Про - посмотреть варианты перевода, примеры использования, найти транскрипцию или прослушать слово. Да, еще одно: список слов поддается сортировке путем щелчка по заголовку столбца.

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

Кому интересно - можно посмотреть (вход, используя аккаунт Google).

Особенность Html.TextBoxFor() в ASP.NET MVC 2

Если вы активно используете HTML хелперы в ASP.NET MVC фреймворке, вам наверняка известен TextBoxFor() - о нем и пойдет речь.

Допустим, вы создаете форму с методом GET с целью организовать фильтр.

Контроллер и модель:

public class HomeController : Controller
{
    private static readonly string[] Fields = new[] {"Ann", "George", "Fred", "Amanda"};

    public ActionResult Search(SearchModel searchModel)
    {
        searchModel = searchModel ?? new SearchModel();
        searchModel.Field = searchModel.Field ?? string.Empty;

        searchModel.Field = Fields.FirstOrDefault(x => x.Contains(searchModel.Field));

        return View(searchModel);
    }
}

public class SearchModel
{
    public string Field { get; set; }
}

Представление:

<% using (Html.BeginForm("Search", "Home", FormMethod.Get)) { %>
    <%= Html.TextBoxFor(x => x.Field) %>
<% } %>
<form action="<%= Url.Action("Search") %>" method="get">
    <input id="Field" name="Field" type="text" value="<%= Model.Field %>" />
</form>

Запустив приложение, получим:

Введем во второе поле "g" и отправим форму нажатием на Enter. Вот что придет в ответ:

Почему в первом поле "g", когда должно быть "George", как во втором? Все просто, фреймворк анализирует строку запроса, и предпочитает значение Field=g из нее значению, приходящему в модели (Model.Field), что не плохо учитывать при разработке.

При этом, если интересно, вот во что рендерится представление:


вторник, 23 августа 2011 г.

Полезное приложение expect (Linux)

Понадобилось автоматизировать процесс развертывания свежей версии веб-приложения на Django из SVN-репозитария.

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

Рассмотрим подробнее - необходимо выполнить:

django-admin.py flush --pythonpath . --settings settings

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

Как организовать эмуляцию ввода?

echo yes|django-admin.py flush --pythonpath . --settings settings

А как быть с вводом нескольких строк?

django-admin.py flush --pythonpath . --settings settings << EOF
yes
yes
admin
...
password
EOF

Все хорошо, да вот пароль так ввести не получится.

Выход? Правильно - expect!

Создаем следующий скрипт flush.exp:

spawn django-admin.py flush --pythonpath . --settings settings
expect continue { send yes\r }
expect create { send yes\r }
...
expect Password { send password\r }
expect again { send password\r }
close

Все! Теперь осталось выполнить:

expect -f flush.exp

О назначении команд скрипта догадаться не сложно, на этом все.

пятница, 19 августа 2011 г.

Sharing ASP.NET MVC views across multiple projects (apps)

Если ведется разработка нескольких проектов, использующих ASP.NET MVC, вполне возможна ситуация, когда появляются представления (views), или частичные представления (partial views) с идентичной функциональностью. Например, календарь для выбора даты. Но попытка получить из одного приложения доступ к ресурсам другого будет пресечена политиками безопасности (что, в принципе, разумно).

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

Для решения задачи целесообразно применить возможность IIS создавать виртуальные директории. Теперь, при разворачивании (deployment) решения, необходимо создать одну физическую директорию (physical directory), содержащую общие представления (shared views), и после этого создать по виртуальной директории (virtual directory) для каждого проекта, которые будут отображаться на эту единственную физическую.

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

понедельник, 15 августа 2011 г.

IIS Restart

Опытные разработчики скорее всего знают, но все равно отмечу, что iisreset (из командной строки) работает более надежно, чем перезапуск сервера (Restart) с помощью консоли управления (IIS Management).

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

вторник, 2 августа 2011 г.

ASP.NET MVC, ORM, ReflectionPermission и Trust Level

Используя ORM в проекте ASP.NET MVC, который хостится на IIS, можно столкнуться с ошибкой системы безопасности вроде "System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.ReflectionPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.".

При этом приложение имеет Full Trust Level (...trust level="Full"... в конфиге, что также подтверждается, если заглянуть в консоль управления IIS).

Проблема может быть связана с текущим значением Application Pool Identity (запрет превыше разрешения) - в данном случае использование NetworkService решило проблему, так как у AppPoolIdentity отсутствовали необходимые разрешения.

воскресенье, 24 июля 2011 г.

Треугольная периодическая функция

Задача. Есть алгоритм, работающий с некоторым рядом значений. Нужно учесть периодичность следующего характера: например, 1, 2, 1, но не 1, 2, 0; значения в общем случае действительные, целочисленные использованы здесь для простоты). Т. е. нужна функция, принимающая на вход значение без учета периодичности и возвращающая корректное значение с учетом периодичности, так, чтобы возвращаемое значение принадлежало валидному диапазону.

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

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

/*!
 Represents triangular periodic function with shape 
 {min, min}, {max, max}, {min, min} and period equal to 2*(max - min).
 Third parameter are value that needs to be bound 
 within min and max using periodic nature of function.
*/
inline float TriangularPeriodicFunction(float min, float max, float val)
{
 // shifting coordinate system so function is above x axis now
 // (and performing inverse shift when result is obtained)
 if (min < 0)
  return TriangularPeriodicFunction(0, max - min, val - min) + min;

 // function is symmetric relative to axis of values
 val = fabs(val);
 
 // length of monotonous interval (MI)
 float len = max - min;
 // index of MI
 int d = (int) floor(val/len);
 // index of value within MI
 float m = fmod(val, len); 

 if (d >= 0)
  // MI is at the right side (relative to the y axis)
  return d&1 
   ? max - m // values within MI are decreasing
   : m; // values within MI are increasing
 else
  // MI is at the left side (relative to the y axis)
  return d&1 
   ? m - max // values within MI are increasing
   : m; // values within MI are decreasing
}

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

До преобразования (функция с минимумом -2, максимумом 2):

После преобразования:

После этого определяется индекс монотонного интервала (МИ) с целью узнать - возрастает ли он, или убывает.

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

Код протестирован и работает для действительных чисел.

четверг, 21 июля 2011 г.

Visual Studio: доверяй, но проверяй... себя!

В предыдущем посте я выразил недоверие к Visual Studio's Clean Solution. Я был не прав - нужно было проверить настройки Configuration Manager, где следует отметить все проекты, подлежащие сборке при построении билда решения.


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

вторник, 19 июля 2011 г.

Visual Studio: когда Clean Solution не помогает

UPD. На самом деле все ОК - подробнее в этом сообщении.

Сегодня столкнулся со странной проблемой: после внесения изменений в код проекта, использующего ASP.NET MVC, и полного ребилда сервер (для отладки использовался локальный IIS) исполнял старую версию.

Очистил решение, собрал - результат тот же, и если поставить брейкпоинт где-нибудь, то он деактивируется по причине вроде "The breakpoint will not currently be hit. The source code is different then the original version.".

Решение проще простого - вручную удалить папку bin и пересобрать проект. Почему я не применил его сразу, а потратил время на копание в настройках проекта и документации? Доверял среде, выполняя Clean Solution. Вот так - доверяй, но проверяй.

суббота, 2 июля 2011 г.

Visual Studio 2010: невозможно заново подключить System.Core.dll

Недавно столкнулся с тем, что в MSVS 2010 невозможно заново подключить System.Core.dll в проект. Оказывается, это известная проблема. Решение - добавить нужную ссылку вручную, открыв файл проекта в текстовом редакторе:
<ItemGroup>
    ...
    <Reference Include="System" />
    <Reference Include="System.Core" />
    ...
</ItemGroup>

пятница, 1 июля 2011 г.

CUDA 4.0: решение проблем при сборке примеров

Честно следуя инструкциям из NVIDIA CUDA C Getting Started Guide for Microsoft Windows, я дошел до пункта "Verify The Installation", где предлагается скомпилировать примеры и запустить bandwidthTest.

Отлично, открываю файл решения для Студии 2010, и запускаю построение. Результат - ошибка: при линковке не найден shrUtils32D.lib.

Обзор папки, в которой размещается SDK (\NVIDIA GPU Computing SDK 4.0), позволил найти shrUtils_vs2010.sln (\NVIDIA GPU Computing SDK 4.0\shared), но при его построении тоже возникли ошибки - не был найден stopwatch.cpp, а также stopwatch_win.cpp. Решение несложное - найти эти файлы в содержимом SDK и добавить их в проект.

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

Таким образом, нужно выполнить следующие шаги (используется VS 2010):
  1. Открыть решение shrUtils_vs2010.sln.
  2. Добавить в него stopwatch.cpp, а также stopwatch_win.cpp (искать в содержимом SDK).
  3. Собрать решение shrUtils_vs2010.sln.
  4. Открыть решение bandwidthTest_vs2010.sln и собрать его.
  5. Запустить приложение bandwidthTest и убедиться в корректности его работы.

воскресенье, 26 июня 2011 г.

Знакомство с разработкой для Android

Мобильные платформы - вещь интересная - привлекали меня давно. И вот теперь, имея на руках устройство с Андроидом на борту, просто руки чешутся :) попробовать разработать что-нибудь для него.

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

Вот так Cadence выглядит на эмуляторе:


Теперь осталось только разобраться как размещать приложения в Android App Market.

Впечатления:

  • порог вхождения достаточно низок, даже без опыта программирования на Java (мой случай) - примерно 6-7 часов на чтение "The Busy Coder's Guide to Android Development" (читается легко; практически без воды и в основном по делу), и около 2 часов на просмотр документации по Java и разработку в IntelliJ IDEA (очень порадовала, все удобно и быстро);
  • отладка: что-то определенное сказать сложно - само приложение простое и не требует особых усилий в этом направлении, единственное - эмулятор не особо шустрый.
Исходный код в открытом доступе (рефакторинг логики и локализация не помешают, но в целом - это работоспособное приложение).

среда, 15 июня 2011 г.

Оптимальный каденс и соответствующая ему скорость

Недавно задался вопросом - а оптимальный ли у меня каденс (частота педалирования)? (Что такое каденс и почему он так важен можно прочесть, например, здесь.)

Что нужно для ответа?

  1. Определиться с диапазоном. Тут все в порядке - в Интернете часто встречается рекомендация поддерживать каденс не ниже 60 об/мин, отсюда диапазон - 65-95 об/мин.
  2. Сравнить желаемый диапазон с реальным, чтобы сделать вывод об оптимальности.
Итак, осталось узнать свой реальный каденс. Как это сделать? Например, можно купить велокомпьютер, измеряющий каденс. А можно, зная свою скорость и текущую передачу, вычислить каденс, но делать такое в уме на ходу мягко говоря не комфортно, поэтому есть вариант проще - определить по диапазону каденса интервал скоростей для каждой передачи. Теперь, сравнив свою текущую скорость с полученными значениями, можно будет сделать вывод об оптимальности каденса.

Зависимость между скоростью и каденсом:

Скорость [км/ч] = Каденс [об/мин] * 60 [мин/ч] * Передача * Пи * Диаметр [дюйм] * 2.54 [см/дюйм] * 0.00001 [км/см],

где Передача - отношение числа зубцов ведущей звезды к ведомой, Диаметр - соответственно диаметр ведущего колеса.

Теперь легко определить оптимальную скорость езды на каждой передаче. Например, на LeaderFox Away 2010 передвигаться на передаче 2-4 (ведущая-ведомая) следует со скоростью 17-24 км/ч, чтобы поддерживать каденс 65-95 об/мин.

Конечно же, вручную считать дело неблагодарное, поэтому был написан небольшой онлайн-калькулятор, доступный по адресу http://py-sandbox.appspot.com/cadence.

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

суббота, 23 апреля 2011 г.

Очистка std::ostringstream (C++ stdlib)

Для экономии времени я (наверное, как и многие разработчики) привык разбираться с любым API "на лету", т. е. исходя из названий классов/интерфейсов/методов/т.д. Но вот здесь этот метод не сработал, пришлось заглянуть на cplusplus.com.

Итак, нужно очистить ostringstream.

Первое, что приходит на ум:

std::ostringstream out;
out << "foo";
out.clear();
out.str(); // == "foo"

Но нет, нужно так:

std::ostringstream out;
out << "foo";
out.str(std::string());
out.str(); // == ""

Вот теперь все в порядке.

воскресенье, 10 апреля 2011 г.

Acer Aspire One D250: реальная скорость передачи данных по WiFi

Являясь обладателем Acer Aspire One D250-0Bw, мне надоело перебрасывать данные с декстопа на нетбук посредством флешки (в мое оправдание - это бывает достаточно редко). Поэтому было решено наконец-таки приобрести WiFi адаптер для десктопа и организовать домашнюю беспроводную сеть. Все прошло удачно (в Сети достаточно руководств, как настроить WiFi сеть и расшарить Интернет-соединение).

И вот наступило время протестировать сеть под настоящей нагрузкой - перебросить гигабайт 30-40. Ок, начинаем копирование: все хорошо, но скорость 3,2 Мб/сек (или 25,6 Мбит/сек). Хм, странно, ведь скорость подключения 54 Мбит/сек и уровень сигнала отличный! Как оказалось 54 Мбит/сек - это теоретический максимум для 802.11g, реальное среднее значение колеблется около 20 Мбит/сек. Отлично! Выше среднего "из коробки", без доп. настроек!

И зачем я это написал, если подобную информацию легко можно найти в Сети? А вот зачем: скорость получилось увеличить. Панель управления - Система - Оборудование - Диспетчер устройств - Сетевые платы - Сетевой адаптер Broadcom 802.11g - Свойства - Дополнительно. А дальше как на скрине (кликабельно).


В результате скорость возросла до 3,9 Мб/сек (или 31,2 Мбит/сек) - не фонтан конечно, но уже лучше!

суббота, 9 апреля 2011 г.

Жучка или Отчет о поиске 2

С целью повысить удобство пользования Жучкой я решил написать web-версию с использованием Google App Engine в качестве фреймворка.

Нельзя сказать, что разработка отняла слишком много времени, но некоторые вещи потребовали дополнительного внимания. Результат можно посмотреть на search-report.appspot.com.

Консольная версия тоже претерпела улучшения - теперь достаточно только файла с поисковыми фразами.

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

Пример выполнения на localhost (dev_appserver).


Пример выполнения на appspot.


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

пятница, 1 апреля 2011 г.

Extreme Programming Night 2011

Совсем недавно завершился конкурс Extreme Programming Night, в котором удалось достичь скромного, но результата (4 место).





Фото с конкурса можно посмотреть в этом альбоме.

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

Чуть ниже скриншот и видео моей версии решения.




Релиз для Win32 можно скачать отсюда.
Исходный код в открытом доступе.

четверг, 31 марта 2011 г.

Отчет о поиске для сайта магистра

Всем, кто разрабатывает собственный сайт на портале магистров ДонНТУ, необходимо составить отчет о поиске.

Что это такое? Это информация о количестве документов, найденных разными поисковиками по ключевым фразам, касающимся магистерской работы и выводы.

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

Ссылка: http://www.assembla.com/code/juchka/subversion/nodes

На данный момент приложением уже можно пользоваться - мануал в readme.txt.

P. S. Для тех, кто никогда не пользовался SVN - это не сложно - погуглите "TortoiseSVN Export" (если используете Windows, или "svn export" иначе).

четверг, 17 марта 2011 г.

Проблема "точки и запятой" при преобразовании строки в число с плавающей точкой в .NET (C#)

Достаточно часто возникает задача преобразовать string в float/double. При этом разработчик сталкивается с проблемой "точки и запятой" (разделителя целой и дробной частей десятичной дроби). Задача, в принципе, тривиальная, но все-таки хотелось бы рассмотреть некоторые моменты поподробнее.

Какие есть варианты ее решения?

1) заменить запятую на точку и распарсить:

public static float AsFloat1(this string s)
{
 return float.Parse(s.Replace(",", "."), CultureInfo.InvariantCulture);
}

2) попробовать распарсить с использованием ожидаемой (или как вариант - текущей) локали, и если что не так (FormatException), попробовать распарсить в инвариантной локали (InvariantCulture).

public static float AsFloat2(this string s)
{
 try
 {
  return float.Parse(s, CultureInfo.GetCultureInfo("uk"));
 }
 catch (FormatException)
 {
  return float.Parse(s, CultureInfo.InvariantCulture);
 }
}

3) "более правильный 1-й вариант": заменять запятую не на точку, а на символ, определенный в качестве разделителя в инвариантной локали:

public static float AsFloat3(this string s)
{
 return float.Parse(
  s.Replace(",", CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator),
  CultureInfo.InvariantCulture);
}

Какой же из вариантов наиболее подходящий?

С одной стороны 2-й вариант кажется весьма логичным: от пользователя ожидаются данные в формате, определяемом его локалью (явно, например, через настройки приложения, или неявно), и если что не так, то пытаемся использовать инвариантную локаль.

Но с другой стороны: как у этих методов с производительностью?

private static void Main()
{
 var strings = new[] {"12,3", "12.3"};
 var functions = new Func<string, float>[]
      {
       x => x.AsFloat1(),
       x => x.AsFloat2(),
       x => x.AsFloat3()
      };

 var watch = new Stopwatch();
 var tests = from function in functions
    select new Action<string>(x =>
             {
              watch.Restart();
              var n = function(x);
              watch.Stop();
              Console.WriteLine("String: {0}; Number: {1}; Time: {2} ms.",
                 x, n, watch.Elapsed.TotalMilliseconds);
             });

 var testIndex = 0;
 foreach (var test in tests)
 {
  Console.WriteLine("Method: AsFloat{0}", ++testIndex);
  foreach (var s in strings)
   test(s);
 }
}

Оказывается, что:

Method: AsFloat1
String: 12,3; Number: 12,3; Time: 0,1989 ms.
String: 12.3; Number: 12,3; Time: 0,0018 ms.
Method: AsFloat2
String: 12,3; Number: 12,3; Time: 0,2546 ms.
String: 12.3; Number: 12,3; Time: 44,7575 ms.
Method: AsFloat3
String: 12,3; Number: 12,3; Time: 0,2659 ms.
String: 12.3; Number: 12,3; Time: 0,0032 ms.
Для продолжения нажмите любую клавишу . . .

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

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

воскресенье, 6 марта 2011 г.

"Access volation" при загрузке моделей X-формата (DirectX) в Irrlicht 1.7.2

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

device->getSceneManager()->getMesh("Models/model.x");

Где возникает ошибка (первая строка здесь - это 1019 строка в CXMeshFileLoader.cpp):

u32* data = new u32[datasize];
for (u32 j=0; j<datasize; ++j)
 data[j]=readInt();
if (dataformat&0x102) // 2nd uv set
{
 mesh.TCoords2.reallocate(mesh.Vertices.size());
 u8* dataptr = (u8*) data;
 const u32 size=((dataformat>>8)&0xf)*sizeof(core::vector2df);
 for (u32 j=0; j<mesh.Vertices.size(); ++j)
 {
  mesh.TCoords2.push_back(*((core::vector2df*)(dataptr)));
  dataptr += size;
 }
}

Почему возникает ошибка: всего указателем data адресуются datasize*4 байт памяти, при загрузке модели может оказаться, что mesh.Vertices.size()*size больше, чем datasize*4 (в моем случае так и было) - отсюда и ошибка.

Что предлагается:

u32* data = new u32[datasize];
for (u32 j=0; j<datasize; ++j)
 data[j]=readInt();
if (dataformat&0x102) // 2nd uv set
{
 mesh.TCoords2.reallocate(mesh.Vertices.size());
 u8* dataptr = (u8*) data;
 const u32 size=((dataformat>>8)&0xf)*sizeof(core::vector2df);
 u32 boundary = (datasize << 2)/size;
 for (u32 j=0; j<mesh.Vertices.size() && j<boundary; ++j)
 {
  mesh.TCoords2.push_back(*((core::vector2df*)(dataptr)));
  dataptr += size;
 }
}

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

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

Успешной разработки!

суббота, 22 января 2011 г.

jQuery Validation Plugin и поля формы с одинаковыми именами

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

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