Страницы

Поиск по вопросам

понедельник, 14 января 2019 г.

Как проверить, зашел ли пользователь с мобильного устройства или с компьютера?

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


Ответ

Проверяйте содержимое navigator.userAgent на наличие подстрок "iphone", "android", "blackberry", "webos", и т.д.

Какие практичные методики оптимизации кода OpenGl 3D движков кроме перечисленных ниже вы знаете?

Вертексные буферные объекты. Отрисовка треугольников одного материала для снижения количества переключений между текстурами, цветом и компилированными шейдерами. Удаление из кадра ненужных объектов. Рефакторинг кода стандартными методами. Перенос матричных операций с мировыми координатами объектов в шейдеры. Рендер спецэффектов в другой программе и отрисовка их из готового файла. (Используется больше памяти, но быстрее так как не нужно проводить предварительные расчеты для отрисовки спецэффекта.) Использование diffuse карт для дешевого выбивания полигонов из модели без потери качества. Mipmapping. Использование где это возможно заранее заготовленных карт освещения вместо real-time расчетов Использование triangle strips для экономии памяти. Использование большего числа текстур текстур с размерами кратными степени двойки. Перенос real-time расчета освещения в шейдеры. Исключения из тела главной функции, которая отрисовывает кадр, всех сложных математических операций, замена их заранее обсчитанными статичными объектами. Перенос кода для детектирования столкновений, AI и других функций не связанных напрямую с отрисовкой картинки в отдельный поток выполнения вызываемый с меньшей частотой чем FPS Представление атрибутов вертексов в виде массива структур, а не структуры массивов(x1,y1,z1,x2,y2,z2,x3,y3,z3 вместо x1,x2,x3,y1,y2,y3,z1,z2,z3) Под 3D движком понимается программа обертка над OpenGl, которая подготавливает массив аттрибутов вертексов для подачи в трехмерный конвейер, естественно не поддерживающая программный рендеринг при котором сам конвейер запрограммирован внутри кода движка. Под оптимизацией понимается оптимизация по многим параметрам, быстродействию, качеству картинки, экономии памяти, читабельности кода и.т.д Интересуют только реальные методы легко и быстро реализуемые на практике прикладным программистом. Методы из советского ВТУЗовского курса вычислительной математики и численных методов, а также алгоритмические-компиляторные методы вроде замены деления на два битовым сдвигом повсюду внутри кода просьба не предлагать.


Ответ

Навскидку: Атласы - замена мелких текстур одной большой (что-то похожее видел в Вашем посте, но недопонял, о чём речь там). Occlusion query - отрисовываем простейшую модель вместо сложной, спрашиваем у видеокарты, сильно ли она перекроется, и узнаём, надо ли её рисовать. Использование временной когерентности для того же отбрасывания невидимых объектов. Instancing. Вообще говоря, Вы мешаете в кучу и графику, и игровую логику, так что конкретный ответ дать сложно. Более того, некоторые техники взаимоисключающие. Оптимизации применяются тогда, когда возникают узкие места, иначе толку от них нет. Например, если Вы упёрлись в fillrate, никакое применение VBO толку не даст, и наоборот, если основная проблема в диком количестве геометрии - можно не заморачиваться с атласами, оптимизацией шейдеров и тд,а сосредоточиться на отбрасывании невидимых треугольников и LOD. В общем случае, на неполностью загруженную видеокарту пытаются переложить все распараллеливающиеся задачи, а не только графику, в то время как процессору обычно отдают игровую логику(если видеокарта занята).

Ошибка со стеком: Thread stack overrun

update `t_map_atms` set phone='3e43' WHERE id=37 Для проверки дала такой вот простенький запрос. Вышло: #1436 - Thread stack overrun: 8240 bytes used of a 131072 byte stack, and 128000 bytes needed. Use 'mysqld --thread_stack=#' to specify a bigger stack. Гуглила. Нашла вариант, как исправитья: в файле my.cnf надо одну строчку привести к виду thread_stack = 256K такого файла не нашла, нашла только my.ini. Подобной строки нет, сама вставила (для эксперемента), но не работает. Что мне делать?


Ответ

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

В каких случаях NoSQL базы явно лучше Relational Databases?

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


Ответ

Есть мнение, что разработчик должен смотреть на структуру данных, которые он хочет хранить. И потом, исходя из этого, уже выбирать где это будет удобнее хранить. Если все сведется к тому, что данные легко и очевидно ложатся на key-value — вот и случай, когда реляционные БД не будут нужны (будут избыточны). Например, если все что надо держать в БД — текущие прогнозы погоды по городам или сессию со списком-историей последних просмотренных, ходящим по видеохостингу пользователем, клипов, то что-то типа memcached или Redis будет вероятно близко к оптимальному решению. Обратный подход (есть БД, нужно запихать в нее определенных данные) имеет смысл если речь идет о уже имеющейся инфраструктуре. Там неудобства разработки компенсируются неудобством введения и обслуживания новых элементов (еще одной БД) в уже имеющуюся инфраструктуру.

Стоит ли использовать БЭМ [закрыт]

Добрый день! Стоит ли использовать БЭМ (Блок Элемент Модификатор (Яндекс)) и, что означает независимый блок в контексте БЭМ?


Ответ

БЭМ, это соглашение о наименованиях. Не MVC, и не исключает совместное использование с каким-нибудь MVC.
БЭМ помогает решить ряд определенных проблем:
Исключить зависимые имена классов. При разработке долгоиграющих проектов или при большой команде это приводит к разъезжающимся страницам Существенно уменьшить усилия на изучение проекта для нового разработчика. Все части вёрстки разложены по файлам и папкам с интуитивно понятными именами Избавиться от копипаста в рамках страницы/сайта/портала. Блок это готовая часть вёрстки, его можно и нужно повторно использовать. Элементы и модификаторы позволяют точечно вносить изменения для каждого случая использования этого блока, избегая взаимное влияние использования модифицированных блоков на одной странице Избавиться от копипаста, если необходимо внести изменение в определенный компонент вёрстки. Не нужно делать правки в 100500 местах, правки вносятся в одном месте
Ценой этого является высокий порог входа к использованию БЭМ. Это принять БЭМ в сердце, разобраться с инструментами сборки, применимыми к вашему случаю, донести БЭМ до окружающих коллег. Стоит ли заплатить эту цену, решать вам.
Про АНБ в контексте БЭМ хорошо сказано здесь https://ru.bem.info/forum/issues/-46/
По сути это два правила:
Всем элементам внутри блока надо задать классы, т.е. не опираться в CSS на имена элементов Все классы, на которые накладываются стили этого блока, должны быть уникальными, например, начинаться с имени класса корневого элемента

Как сделать перенос в ячейке при работе с phpexcel

Доброго всем времени суток господа Пользуюсь phpexcel'ем, причем не первый день. Одну штуковину упорно не могу найти в мануале (или нет ее там). Ищу перенос внутри ячейки. Вот допустим вам нужно вставить 200 знаков в ячейку, и они не влезают. В экселе есть кнопка - перенос текста. Вот интересует как нужную ячейку отформатировать, что бы этот перенос был. Можно ли так вообще? Смысл в том, что текст помещается в ячейке, путем автоматического переноса по строкам. Вот собственно и все, только команды не знаю, ее и спрашиваю. p.s. // выдернул из кода
// выравниваю как надо $page->getStyle("".$jax."".$stroka."")->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT); $page->getStyle("".$jax."".$stroka."")->applyFromArray(array("font" => array( "bold" => true)));
// вставляю данные, и проклятая переменная $for, неприлично длинная $page->setCellValue("".$jax."".$stroka."", "".$for."");


Ответ

Насколько мне не изменяет память, то так: $page->getStyle("".$jax."".$stroka."")->getAlignment()->setWrapText(true);

Подключение DirectX к проекту WPF

Пишу небольшую игрушку на WPF, и для одновременного воспроизведения многих звуков использую DirectSound. До этого пытался использовать AudioVideoPlayback, но была точно такая же проблема. Я добавил в проект ссылку на DirectSound.dll из папки DirectX. Прописал using Microsoft.DirectX.DirectSound; Вот эти строки отвечают за инициализацию: Microsoft.DirectX.DirectSound.Buffer sp; Microsoft.DirectX.DirectSound.Buffer deathSp; Device m_SoundDevice; В конструкторе окна выделяю память, подгружаю все: m_SoundDevice = new Device(); m_SoundDevice.SetCooperativeLevel((new system.Windows.Interop.WindowInteropHelper(this)).Handle, CooperativeLevel.Priority);
sp = new Microsoft.DirectX.DirectSound.Buffer("Shot2.wav", m_SoundDevice); deathSp = new Microsoft.DirectX.DirectSound.Buffer("Death1.wav", m_SoundDevice); Проблема состоит в том, что если в свойствах проекта стоит .NET 4.0 или выше, то при отладке студия иногда просто зависает, и закрывается только завершением процесса студии, иногда сразу же выдает ошибку, как при версиях 3.Х. Скомпилированный при этом экзешник выдает ошибку при запуске. Если понизить версию .NET до 3.5 или 3.0, то при отладке программа запускается, но вылетает при инициализации, которую я указал выше. Пишет следующее: Нет доступных исходных файлов. В стеке вызова содержится только внешний код. XamlParseException не обработано "Вызов конструктора для типа "Game.MainWindow", удовлетворяющего указанным ограничениям привязки, привел к выдаче исключения.": номер строки "3" и позиция в строке "9". Я не пойму, в чем причина. Где эта третья строка - тоже. В xaml в 3ей строке ничего интересного, как и в самом коде на 3ей строке.


Ответ

Уфф, я разобрался в проблеме. Причина была в том, что задавать CooperativeLevel для SoundDevice нельзя во время инициализации нашего MainWindow. Инициализацию всего DirectSound нужно вешать на событие OnLoad нашего главного окна, либо в любой момент после завершения его инициализации.

Документация Java (Android) в Intellij IDEA

Начал изучать Android, в качестве IDE использую Intellij IDEA, до этого писал на C# в VS. Где найти комментарии или документацию к классам и методам в стандартных пакетах Android? В VS, например, при наведении на неизвестный класс или метод отображается подсказка-описание, которое помогает понять что к чему. А в Android (или точнее будет Java) как что-то подобное осуществить? Интересует именно подсказки в IDE , а не ссылки к оф. документации Android http://developer.android.com/reference/packages.html и все в таком духе.


Ответ

Советую ознакомиться с IDEA keymap: Windows/Linux, Mac По нажатию ctrl+Q с кареткой на имени метода/класса вызывается quick documetation popup

Артефакты в коде

После сборки выполняемого файла или библиотеки добавляет ли компилятор информацию о себе?


Ответ

Да, обычно добавляет. Не всегда правда явную. Некоторые иструменты (к примеру PeID) могут распознать компилятор (иногда с точностью до билда), ориентируясь на особенности генерации кода. upd Microsoft известна тем, что добавляет в exe несколько байт, о значении которых люди долго спорят. Ещё немного.

Инсталлер для Qt-приложения

Здравствуйте. Что-то сходу ничего не нашел, поэтому спрошу здесь. Есть ли какая утилитка, которая сделает проект Qt (exe + необходимые dll) инсталлятором со стандартными настройками (путь, запуск после установки и пр.)? UPD: Все необходимые файлики я ей сам скормлю, т.е. дело даже не в Qt, а в том как из набора exe+dll's получить не архив, а привычный пользователю установщик? Должны же быть где-то такие. Я думаю всякие "репакеры" программ и софта ими пользуются.


Ответ

Видимо Вам установщик нужно сделать: посмотрите в сторону NSIS - http://ru.wikipedia.org/wiki/Nullsoft_Scriptable_Install_System

Сохранение пароля браузером при Ajax авторизации

Добрый день. Так получилось, что авторизация у меня происходит так: Пользователь вводит данные, и при нажатии кнопки "вход" информация обрабатывается через ajax-запрос. При удачном логине страница просто обновляется. При таком подходе браузер не запоминает пароли(я имею в виду эти окошечки "сохранить пароль?").. А я хочу, чтоб сохранял, функция-то удобная. Какие бы костыли сделать?


Ответ

Я задавал такой же вопрос на Хабре и получил отличный ответ:
1. Сделайте себе фейковый адрес который ничего не делает и возвращает 200 ответ 2. Форме укажите этот фейковый адрес и _target=«iframe_name» (естественно фрейм должен быть) 2. Перед аяксовой отправкой данных на правильный адрес, делайте реальный сабмит формы. 3. Логиньтесь аяксом, смотрите как браузер спрашивает не запомнить ли логин/пароль 4.!!! 5. PROFIT!

Как запустить заданное количество вложенных циклов без рекурсии

допустим есть функция void cicl(){ for(...){ for(...){ ` for(...){ cout << "работает вложенных три цикла" << endl; } `} } } а если надо такую функцию которая создает 10000 вложенных циклов. void cicl(unsigned int num_cicle=10000){ // не будем же мы здесь писать 10000 вложенных циклов } как осуществить такое не прибегая к рекурсии?


Ответ

Если нужно организовать вложеные циклы, то нужен только массив для хранения индексов. Пусть нужно n вложенных циклов, но максимальное значение - m. #include #include
using namespace std;
int main() { const int n = 3; const int m = 4; int ind[n] = {0}; int c = pow(m,n); // степень, может быть вычислена сразу. for (int i = 0; i < c; i++) { // это такое тело цикла - вывод индеков for (int j = 0; j < n; j++) { std::cout << ind[j] << " "; } std::cout << std::endl;
// ключевая часть - обновим индексы for (int j = 0; j < n; j++) { ind[j]++; if (ind[j] < m) break; ind[j] = 0; }
} return 0; } Если индексы должны быть разные, то нужен ещё один массив индексов и проверки должны быть не с m, а с элементами этого массива. У этого кода есть много недостатков, к примеру, можно от параметра цикла i избавиться (при больших вложенности может быть переполнение). Но это легко при желании доработать. Также, возможно, нужно будет использовать вектор. Но не буду же я весь код за Вас делать:) По факту - это идентично обычной позиционной системе счисления.

Сохранение данных Android

[Совет][Теория] Доброй ночи, хэшкодовцы =) Мне стало интересно как лучше сохранять данные, которые вводит пользователь. В моем случае это пароль & логин. Что я под этим имею: Записывать данные в базу SQLite / на память телефона в файл и тому подобное. Примером для понимания моего вопроса можно взять любое социальное приложение. Одноклассники, Вконтакте, Mail.Ru Agent, WeChat и другие.


Ответ

Теория В теории нельзя хранить пароли. Хранятся только пары логин и хэш пароля, лучше всего хранить хэш и отдельно от хэша соль к паролю, так чтобы: хэш строка=хэш(пароль+соль) //хэш функция например MD5 или SHA1 Проверка пароля осуществляется в этом случае так: Юзер вводит логин и пароль По логину находим хэш строку (из БД) По логину находим соль (в идеале в другом файле/бд) Вычисляем хэш как хэш(введенный пароль+соль) Сравниваем полученное значение с хранящимс в БД хэшем В случае успеха пускаем, в случае неуспеха отражаем Совет Для логин/хэш создаем таблицу SQLite с индексом по логину Для вычисления хэша чаще всего используется MD5 или SHA1, правда некоторые православные криптографы считают их слабыми и рекомендуют другие. Обзор криптографических хэш функций здесь Соль генерируем случайно и храним в преференсах

Сохранить результат команды в переменную

Пытаюсь получить результат так. read engine <<< ibus engine echo $engine но выдает пустую строку. Если просто написать ibus engine то выдает результат команды, но мне нужно сохранить результат в переменную Подскажите как. Спасибо


Ответ

Команду в скобки: $(команда) RESULT=$(ibus engine) echo $RESULT

Как на Bitbucket.org добавить второе рабочее место? (Для записи в репозитарий)

Есть проект на Butbucket (приватный). До недавнего времени использовал Bitbucket практически как резервоное копирование, соединяясь с одного рабочего места. Теперь мне нужно добавить второй компьютер, с которого я работаю. И сделать возможность пушить изменения. На втором рабочем месте я сгенерировал пару открытый-закрытый ключ, открытый добавил в «Settings»-«Ключи развертывания». Но там написано следующее: «Используйте ключи развертывания для получения доступа на чтение к этому репозиторию». То есть, пушить со второго рабочего места не могу. Git говорит следующее: > git push conq: repository access denied. access via a deployment key is read-only. fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists. На вкладке «Settings»-«Управление доступом» есть только один пользователь, который создался при создании репозитария, и под которым я могу работать с первого рабочего места. На втором рабочем месте у меня настоен тот же самый логин и емайл пользователя (ведь я тот же самый человек). Но со второго рабочего места пушить не могу. Вот здесь нашел совет: http://friendfeed.com/bessarabov/619035bd/email?embed=1 Чтобы дать доступ к приватному репозиторию, нужно указать email человека, а не его логин на битбакете. Решил в управлении доступом сделать вторую запись, но указать не логин (который уже там есть), а емайл. В результате битбакет показывает ошибку: {«error»: {«message»: «'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)», «detail»: " File \«/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/piston/resource.py\», line 208, in __call__
result = checked_meth(request, *args, **kwargs)
File \«/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/piston/resource.py\», line 195, in checked_meth
return meth(*args, **kwargs)
File \«/opt/python/domains/bitbucket.org/current/bitbucket/local/env/lib/python2.7/site-packages/newrelic-2.18.1.15/newrelic/hooks/component_piston.py\», line 33, in __call__
return self._nr_wrapped(*args, **kwargs)
File \«/opt/python/domains/bitbucket.org/2014-05-07/bitbucket/../bitbucket/apps/bb/decorators.py\», line 38, in wrap
return f(request, *a, **kwa)
File \«/opt/python/domains/bitbucket.org/2014-05-07/bitbucket/../bitbucket/apps/api/v10/decorators.py\», line 386, in wrapper
resp.content = str(e)
", «id»: «b46672c0ff36478e9140bc8bd8a47cbd»}} Я что-то вообще туплю. Такое простое действие, как добавить второе рабочее место, не могу сделать. Помогите плз.


Ответ

В общем, искал настройки не там. Оказывается, настройки аккаунта находятся не в Settings, а отдельно (клик на аватар, выбрать Управление аккаунтом). Там в разделе SSH ключи надо добавить новый ключ. Ключ в разделе Settings - Ключи развертывания надо предварительно удалить, а то система не даст добавить новый ключ.
Но багрепорт надо запилить. У них раскрытие пути прямым текстом, и никого не волнует, что удивительно.

Что такое обертка класса?

Пожалуйста, ребята, объясните что такое обертка класса, например, в Java! Вот, например, есть значимый тип данных "int" - который 4 байта и может хранить целочисленное число. Я думал что тип "int" это просто самостоятельный тип и когда мы объявляем "интовую переменную" то компилятор просто видит ключевое слово int и понимает что необходимо выделить 4 байта памяти в стеке и положить туда значение. Но у него есть класс обертка Integer - это как? Класс который описывает как должна работать "интовая переменная"? То есть компилятор всегда обращается к этому классу если я объявляю "интовую переменную"?


Ответ

То есть компилятор всегда обращается к этому классу если я объявляю "интовую переменную" Нет, интовая переменная это просто интовая переменная. Классы Integer, Long, Double и им подобные обертки для примитивных типов нужны, главным образом, для использования в коллекциях, т.к. коллекции в Java могут работать только со ссылочными типами данных (наследниками класса Object). Т.е. вы не можете объявить, например, список List, поэтому объявляете его с использованием обертки: List. Кроме того, эти классы-обертки содержат ряд вспомогательных методов для работы с соответствующими примитивными типами. Обновление Да, и обратите внимание на разницу между строками: Integer a = 5; Integer b = 5; Integer c = new Integer(5); В первых двух случаях значение упаковывается (boxing) в обертку неявно. В результате Java инициализирует переменные a и b не через new, а через Integer.valueOf(). В результате значения кешируются (только для определенного часто используемого диапазона чисел), что сэкономит нам память: System.out.println(a == b); // 'true' При ручной упаковке вы гарантированно создаете новый экземпляр: System.out.println(a == с); // 'false'

Как переименовать любой коммит в git?

Хочу переименовать десяток коммитов, но что-то не могу разобраться, как это сделать. Вот, к примеру, статья тут, но у меня загвоздка после git rebase --interactive, то есть редактор открывается такой же, но а дальше куда и что писать? Если пытаюсь написать что-то, то у меня почему-то пишет в самом низу и по одному символу. Делал я это на windows через терминал в SourceTree. Может, есть какой-то другой способ?


Ответ

git rebase --interactive вам покажет в текстовом редакторе своего рода план: список коммитов и действий, которые к ним будут применены. По умолчанию всем коммитам сопоставлено действие pick - сохранить как есть. Ваша первая задача отредактировать действия на свой вкус. Доступные действия описаны в комментарии, отбитом символом # # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell Вас в первую очередь интересует команда r reword - изменить текст сообщения. Не знаю, как SourceTree, а обычный шелл из пакета msysgit (мы ведь о Windows говорим?) предлагает в качестве редактора православный vim. Если у вас так же, и вы с ним не знакомы - смело давите кнопку i на клавиатуре и vim перейдет в режим редактирования. У нужных коммитов замените pick на reword. Теперь надо вернуться в командный режим, нажав Esc. Сохраняемся и выходим - набирайте на клавиатуре :wq, жмите Enter Редактор закроется, и git приступит к выполнению вашего плана. Для каждого коммита, помеченного действием reword, он откроет вам редактор и предложит отредактировать сообщение. Опять-таки, если у вас vim - жмем i, редактируем, Esc, сохраняем :wq. На комментарий под текстом коммита, отбитый решеткой, не обращайте внимания. Он просто подсказывает вам, что делать, и в текст сообщения не попадет.

Как запретить останавливать сервис при блокировке экрана?

Здравствуйте, у меня есть приложение, которое отправляет данные на сервер каждые 5 минут по wi-fi. Я написал сервис, в котором реализовал пару таймеров. При закрытии приложения все работает прекрасно, но стоит нам дождаться момента, когда экран погаснет, сервис перестает отсылать данные. Но стоит нам зажечь обратно экран, как приложение опять начинает отсылать данные. Я хочу добиться того, чтобы сервис не останавливался, т.е. данные отсылались всегда, независимо от состояния экрана. Вы можете что-нибудь посоветовать? Спасибо всем за ответы, мне помогло использование Power Manager PARTIAL_WAKE_LOCK http://developer.android.com/reference/android/os/PowerManager.html . Правда пришлось пожертвовать расходом энергии


Ответ

CWAC Wakeful, например. Но за такие решения авторов надо сжигать на кострах, ибо оно батарею сжирать будет постоянно.

Случайное число в диапазоне от -10 до 10 в Java.

Друзья, приветствую!
Необходимо сгенерировать случайное число в диапазоне от -10 до 10. nextInt() не позволяет этого. Подобный вопрос задавался, но не могу осилить написанное (мне необходим код целиком).
Не так давно начал изучать Java, не будьте строги. Заранее спасибо!


Ответ

Тогда, видимо, нужно выбросить книгу, по которой Вы учитесь, если не можете написать что-то вида: import java.util.*; import java.lang.*; import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */ class Ideone { public static void main (String[] args) throws java.lang.Exception { Random r = new Random(System.currentTimeMillis()); for (int i = 0; i<1000;i++) { int q = r.nextInt(21) - 10; System.out.println(q); } } } А вот почему там 21 и 10 - это уже домашнее задание. Обновление Random принимает параметром seed - такой специальный параметр для генерирования последовательности. В многих языках функция random сделана так, что если начальное значение одинаковое, то и последовательность будет одна и та же. Это сделано в целях отладки и детерминированности (то есть чтобы все было стабильно и повторяемо) программ. А вот задание в качестве seed текущего времени (которое не повторяется) дает возможность генерировать разные последовательности.

Как правильно писать тег BR?

Возник вопрос по тегу br. Как следует его правильно писать:
,
, или
?


Ответ

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


, и т.д. Написание
- неверно, т.к. BR - одинарный тег, а слэш после открывающей скобки - только для закрывающих дескрипторов.

Как программно закрыть Excel при возникновении исключительной ситуации?

try { excelApp.Workbooks.Open(fileName); //Делаем что-то, что вызывает исключение //System.Runtime.InteropServices.COMException } catch (Exception ex) {
} finally { //При дебаге в этот блок кода заходит, но в процессах //остается висеть EXCEL.EXE excelApp.Quit(); }


Ответ

Народ с английского SO (см.)
Рекомендует добавить:
excelApp.Application.Quit(); excelApp.Quit();

Загрузка ядра linux

Здраствуйте, решил себе ради интереса создать linux дистрибутив.
Собрал ядро, создал загрузочный ramdisk, сделал все что мне нужно в ramdisk
В итоге у меня вышла такая структура каталогов:
Папка boot в ней две папки, первая initrd, вторая kernel, в первой лежит main.gz во второй kernel.lk
Как теперь из этого всего сделать img образ чтоб запустить в эмуляторе? Гугл сказал что мне нужен загрузчик
Много чего в гугле читал но нормального мануала по установке загрузчика для новичка не нашел.
Мог бы кто расказать подробнее, ибо я новичок: первый раз собрал ядро.


Ответ

Смотря какой эмулятор используете, например Qemu поддерживает прямую загрузку ядра и рамдиска. Используй параметры
-kernel bzImage use 'bzImage' as kernel image -append cmdline use 'cmdline' as kernel command line -initrd file use 'file' as initial ram disk
или Воспользуйся virt-manager или virt-install - хорошие менеджеры для qemu.
На других виртуалках можно воспользоваться GRUB или Syslinux. Для этого создайте образ диска dd if=/dev/zero of=newos.img bs=10M count=10. Потом создадим там раздел и файловую систему
$ fdisk ./newos.img
Welcome to fdisk (util-linux 2.26.2). Changes will remain in memory only, until you decide to write them. Be careful before using the write command.
На диске не удалось найти таблицу разделов. Created a new DOS disklabel with disk identifier 0xa17f7b6a.
Команда (m для справки): n Partition type p primary (0 primary, 0 extended, 4 free) e extended (container for logical partitions) Select (default p): p Номер раздела (1-4, default 1): 1 Первый сектор (2048-20479, default 2048): Last sector, +sectors or +size{K,M,G,T,P} (2048-20479, default 20479):
Created a new partition 1 of type 'Linux' and of size 9 MiB.
Команда (m для справки): w The partition table has been altered. Syncing disks. $ sudo partx -a ./newos.img $ sudo mkfs.ext4 /dev/loop0p1
Смонтируй луп и скопируй туда папочку /boot/ и установим туда grub: grub-install --boot-directory=КАТАЛОГ /dev/loop0
И можно отключить образ $ partx -d ./newos.img
В некоторых деталях алгоритм установки скорее всего прийдется подкоректировать. И всеже рекомендую использовать qemu для игр с рамдиском ;)

Не работает базовый метод строки и поиск по строке регулярным выражением

Есть очень примитивный код:
#!/usr/bin/python # -*- coding: utf-8 -*- import re from string import *
text = 'тут будет внедорожник (Туссан, туарег) или Ровер' text = text.lower() #text = text.decode('utf-8') print text
model_list = ['туссан', 'туарег', 'королла', 'нексия']
for model in model_list: response = re.search(model, text, re.IGNORECASE) if response: print 'найдено: ' + response.group(0)
Задача простая - есть список моделей и есть строка текста, по каждой модели списка надо найти вхождение в строку, и вот тут-то проблема:
данный код в том виде как выше в консоли пишет
тут будет внедорожник (Туссан, туарег) или Ровер найдено: туарег
а должен найти явно два авто
если задать переменную так text = u'тот же самый текст ...' или строку text = text.lower() переписать как text = text.decode('utf-8').lower(), то тогда в консоли уже следующее:
тут будет внедорожник (туссан, туарег) или ровер
т.е. регистр стал нижним, но при этом поиск не происходит. Более того, не понятно, почему re.I (или re.IGNORECASE) вообще не работает. Пробовал дописать re.I|re.U|re.S|re.M, ничего не выходит.
В чем тут проблема? Мне всего лишь надо проверить несколько слов в куске текста, при этом без учета регистра.


Ответ

Проблема в кодировке. Вы можете решить её несколькими способами (отсортированно по моему субъективному восприятию удобства способов):
Перейти на Python 3
В Python 3 по умолчанию используются юникодные литералы, поэтому у вас не возникнет подобных проблем. В коде при этом достаточно использовать функцию print вместо оператора, т.е. добавить скобки вызова функции:
import re
text = 'тут будет внедорожник (Туссан, туарег) или Ровер' model_list = ['туссан', 'туарег', 'королла', 'нексия']
for model in model_list: response = re.search(model, text, re.IGNORECASE) if response: print('найдено: ' + response.group(0))
Заметьте также, что нам нет необходимости в Python 3 вручную указывать кодировку файла исходного кода: в Python 3 по умолчанию используется кодировка utf-8. Вставить в начале файла строку
from __future__ import unicode_literals
Эта строка говорит, что в файле все строковые литералы будут иметь тип unicode. Особенно удобно использовать эту возможность для того, чтобы писать переносимый между версиями Python код (в сочетании с остальными возможностями модуля __future__). Выглядеть это будет следующим образом:
# coding: utf-8
from __future__ import unicode_literals import re
text = 'тут будет внедорожник (Туссан, туарег) или Ровер' model_list = ['туссан', 'туарег', 'королла', 'нексия']
for model in model_list: response = re.search(model, text, re.IGNORECASE | re.UNICODE) if response: print 'найдено: ' + response.group(0) Преобразовать используемые строки в юникод. Так вышло, модуль регулярных выражений некорректно обрабатывает кириллицу в байтовых строках (не умеет искать без учёта регистра). Вы можете вызвать преобразование в юникодные строки для нужных переменных:
# coding: utf-8
import re
text = 'тут будет внедорожник (Туссан, туарег) или Ровер' model_list = ['туссан', 'туарег', 'королла', 'нексия']
text = text.decode('utf-8')
for model in model_list: model = model.decode('utf-8') response = re.search(model, text, re.IGNORECASE | re.UNICODE) if response: print u'найдено: ' + response.group(0)
Заметьте, что при выводе результата, строка u'найдено' помечена юникодной. Это важно, потому что складывать можно только строки одного типа, а response.group(0) возвращает нам юникодную строку.
Использовать юникодные литералы вручную: (бывший способ №3)
# coding: utf-8
import re
text = u'тут будет внедорожник (Туссан, туарег) или Ровер' model_list = [u'туссан', u'туарег', u'королла', u'нексия']
for model in model_list: response = re.search(model, text, re.IGNORECASE | re.UNICODE) if response: print u'найдено: ' + response.group(0)

Важно заметить, что при правильном учёте кодировок строк можно пользоваться поиском без учёта регистра, но необходимо добавить флаг re.UNICODE для того, чтобы модуль правильно отрабатывал на юникодных строках.
Также старайтесь в новых проектах использовать Python 3, если нет строгих требований использовать версию Python 2.

Как узнать архитектуру команд процессора в linux?

Встал вопрос, какой пакет установить: http://www.rpmfind.net/linux/rpm2html/search.php?query=qemu-sgabios+noarch.rpm&submit=Search+...&system=&arch=
в /proc/cpuinfo и lscpu показывается только архитектура самого процессора. Я не железнячник, прошу не закидывать камнями.
# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 2 On-line CPU(s) list: 0,1 Thread(s) per core: 1 Core(s) per socket: 2 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 15 Model name: Intel(R) Core(TM)2 CPU 6320 @ 1.86GHz Stepping: 6 CPU MHz: 1600.000 BogoMIPS: 3732.95 Virtualization: VT-x L1d cache: 32K L1i cache: 32K L2 cache: 4096K NUMA node0 CPU(s): 0,1
# cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 15 model name : Intel(R) Core(TM)2 CPU 6320 @ 1.86GHz stepping : 6 microcode : 0xd0 cpu MHz : 1867.000 cache size : 4096 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 10 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm dtherm tpr_shadow bogomips : 3732.95 clflush size : 64 cache_alignment : 64 address sizes : 36 bits physical, 48 bits virtual power management:
processor : 1 vendor_id : GenuineIntel cpu family : 6 model : 15 model name : Intel(R) Core(TM)2 CPU 6320 @ 1.86GHz stepping : 6 microcode : 0xd0 cpu MHz : 1600.000 cache size : 4096 KB physical id : 0 siblings : 2 core id : 1 cpu cores : 2 apicid : 1 initial apicid : 1 fpu : yes fpu_exception : yes cpuid level : 10 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm dtherm tpr_shadow bogomips : 3732.95 clflush size : 64 cache_alignment : 64 address sizes : 36 bits physical, 48 bits virtual power management:


Ответ

Architecture: x86_64
Чем это не устраивает? Архитектура CPU у Вас amd64, она же x86_64.

Не корректное выполнение примера из книги “Python в системном администрировании UNIX и Linux”

Здравствуйте. В книге есть пример:
for i in range(10): !date > ${i}.txt
Который должен показывать взаимодействие ipython с bash, и создавать 10 текстовых файлов с датой, однако у меня создаётся только один файл с именем sh.txt. Что я делаю не так? Версия python 2.7.3, ipython - 0.13.1 Заранее спасибо за ответ.


Ответ

Точно связано с версией IPython. Начиная с версии 0.10 данный пример не работает (в книге использовалась версия 0.8.4), в случае если возле {i} указан символ доллара:
for i in range(10): !date > ${i}.txt
Но без него - действительно получается нужный результат.
В release note не было найдено пояснения этого изменения, возможно, оно связано с чем-то другим.

Как снизить потребление ресурсов в процессе детекции лица?

С помощью класса CascadeClassifier, а в частности его метода detectMultiScale() осуществляется поиск лица в кадре. В целом всё устраивает, кроме повышенного потребления вычислительных ресурсов при в общем-то стандартной кадровой частоте в 30 кадров/сек.
Можно было бы попробовать применить cuda::CascadeClassifier, но останавливает соответствующее требование к железу, плюс особое внимание к сборке как OpenCV, так и самого проекта в виду необходимости использования дополнительных библиотек.
Метод detectMultiScale() принимает на вход параметры, которыми можно снизить нагрузку. Например, значения minSize и maxSize ограничивают допустимый размер лица в пикселях. Регулировка этих параметров избавляет алгоритм от необходимости учитывать все возможные вариации размеров, определяемых с шагом scaleFactor. minNeighbors в свою очередь позволяет избавиться от т.н. false positive срабатываний алгоритма, которые чаще всего указывают на область, не являющуюся лицом. Однако всё это во многом сводится на нет, если требуется ловить лицо как вблизи камеры, так и на некотором удалении от оной. То есть в широком диапазоне размеров.
В поиске решения пришёл к выводу, что высокое видеоразрешение для детекции лица не требуется. Исходя из этого, написал код, который также может помочь в снижении нагрузки на центральный процессор:
// Объект _classifier типа CascadeClassifier // уже загружен соответствующим xml-файлом классификации.
// _scale_factor, _min_neighbors, _min_size, _max_size // также инициализируются заранее в качестве атрибутов класса Detector.
bool Detector::run(const cv::Mat &src_mat, std::vector &rects) { if(src_mat.empty() || _classifier.empty()) return false;
cv::Mat gry_mat; switch(src_mat.channels()) { case 1: gry_mat = src_mat.clone(); break; case 3: cv::cvtColor(src_mat, gry_mat, cv::COLOR_BGR2GRAY); break; default: return false; }
int pyr_cnt = 0; while(gry_mat.cols > 512 || gry_mat.rows > 384) { cv::pyrDown(gry_mat, gry_mat); ++pyr_cnt; }
_classifier.detectMultiScale(gry_mat, rects , _scale_factor, _min_neighbors , cv::CASCADE_FIND_BIGGEST_OBJECT , _min_size, _max_size);
if(rects.empty()) return true;
if(pyr_cnt > 0) { for(int i = 0, n = rects.size(); i < n; ++i) { cv::Rect &rc = rects[i];
int cnt = pyr_cnt; while(cnt--) { rc.x *= 2; rc.width *= 2; rc.y *= 2; rc.height *= 2; } } }
return true; }
Строка while(gry_mat.cols > 512 || gry_mat.rows > 384) {...} определяет, сколько раз нужно уменьшать кадр в два раза. В общем-то, это от "балды" и подставить можно любые значения, нежели чем 512х384, например, в зависимости от предполагаемой удалённости объекта от видеокамеры.
Функция pyrDown(), уменьшающая кадр ровно в два раза, использована по причине того, что отработает быстрее, нежели чем просто задействовать обычно используемую в подобных случаях cv::resize()
К сожалению, этот подход точно также не решает обозначенную ранее проблему. Если необходимо, чтобы лицо фиксировалось на разных расстояниях, различающихся между собой значительно, то можно переусердствовать с уменьшением кадра и тогда вообще ничего не будет детектироваться.
Каким ещё способом можно попытаться решить проблему?


Ответ

Можно использовать оптический поток. Итеративный алгоритм Лукаса-Канаде работает быстро, а с учётом того, что для задачи трекинга лица не требуется большое количество точек интереса, то скорость обработки каждого кадра будет очень высокой.
Действительно, если лицо обнаружено классификатором каскада, то почему бы далее не использовать возможности трекинга с тем, чтобы отследить местоположение объекта интереса на последующих кадрах. Таким образом, всего лишь совместив детекцию и трекинг, получим значительный прирост в производительности.
Важно учесть один момент: детектор всегда выдаёт прямоугольную область, включающую лицо, но никогда обрамляющую её. Это означает, что прежде чем начать искать точки интереса на области лица, эту самую область необходимо уменьшить с тем, чтобы на фон, который безусловно будет виден в оригинальном прямоугольнике, не попало ни одной точки интереса.
Для устранения препоны можно использовать разные методы, а можно просто уменьшить область интереса, сообразуясь с пропорциями ширины и высоты лица. Собственно, для трекинга будет вполне достаточно использовать небольшого размера прямоугольник, полностью размещающийся внутри области лица:
cv::Rect Tracker::getFaceSubRoi(const cv::Rect &face_roi) { cv::Rect sub_roi; sub_roi.x = face_roi.x + face_roi.width * 0.3; sub_roi.y = face_roi.y + face_roi.height * 0.05; sub_roi.width = face_roi.width - face_roi.width * 0.6; sub_roi.height = face_roi.height - face_roi.height * 0.8;
return sub_roi; }
В данном примере коэффициенты подобраны опытным путём для выделения области лба. Можно выбрать свои. Главное, повторюсь, это отсутствие видимости фона за лицом.
Далее необходимо организовать поиск точек интереса на лице, только что обнаруженном детектором, с учётом уменьшенной области интереса:
// Исходный кадр в оттенках серого. cv::Mat gry_mat = ...
// Создаём матрицу маски размером с исходный кадр // и закрашиваем её в уменьшенной области интереса белым цветом. cv::Mat msk_mat = cv::Mat::zeros(gry_mat.size(), CV_8U); cv::rectangle(msk_mat, sub_roi, cv::Scalar(255), -1);
// Максимально допустимое кол-во точек интереса. // Сотни штук обычно за глаза. const int max_num_pnts = 100;
// Минимально допустимое кол-во точек интереса. const int min_num_pnts = 10;
// Находим точки на кадре в области, ограниченной маской. // Прочие параметры устанавливаем по желанию и ситуации. std::vector prv_pnts; cv::goodFeaturesToTrack(gry_mat, prv_pnts, max_num_pnts, 0.001, 5.0, msk_mat, 3); cv::cornerSubPix(gry_mat, prv_pnts, cv::Size(10,10), cv::Size(-1,-1) , cv::TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,50,0.0001));
// Бывают случаи, когда количество обнаруженных точек меньше допустимого. // Тогда со следующего кадра можно опять начать с детекции. if((int)prv_pnts.size() < min_num_pnts) { /* Ругнуться и выйти */ }
// Остаётся построить пирамиду изображений. std::vector prv_pyr; cv::buildOpticalFlowPyramid(gry_mat, prv_pyr, cv::Size(21,21), 3, true , cv::BORDER_REFLECT_101, cv::BORDER_CONSTANT, true);
Теперь имеется всё необходимое, чтобы на следующем кадре производить уже не детекцию, а трекинг.
while(true) { // Читаем кадр в оттенках серого. cv::Mat gry_mat = ...
// Строим пирамиду изображений для следующего кадра. std::vector nxt_pyr; cv::buildOpticalFlowPyramid(gry_mat, nxt_pyr, cv::Size(21,21), 3, true , cv::BORDER_REFLECT_101, cv::BORDER_CONSTANT, true);
// Вычисляем оптический поток, используя "prv_pyr" и "prv_pnts", // полученные ранее. std::vector statuses; std::vector errors; std::vector nxt_pnts; cv::calcOpticalFlowPyrLK(prv_pyr, nxt_pyr, prv_pnts, nxt_pnts , statuses, errors, cv::Size(21,21), 3 , cv::TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,50,0.0001) , cv::OPTFLOW_LK_GET_MIN_EIGENVALS, 0.0005);
// Векторы для хранения смещения каждой из точек интереса по осям. std::vector hrz_offset, vrt_offset;
const int n = nxt_pnts.size(); hrz_offset.resize(n); vrt_offset.resize(n);
int k = 0; for(int i = 0; i < n; ++i) { if(!statuses.at(i)) continue;
const cv::Point2f &prv_pnt = prv_pnts.at(i); const cv::Point2f &nxt_pnt = nxt_pnts.at(i);
// Если точки вышли за границы области интереса, // то не используем их. if(nxt_pnt.x < sub_roi.x || nxt_pnt.x > sub_roi.br().x) continue; if(nxt_pnt.y < sub_roi.y || nxt_pnt.y > sub_roi.br().y) continue;
hrz_offset[k] = nxt_pnt.x-prv_pnt.x; vrt_offset[k] = nxt_pnt.y-prv_pnt.y;
nxt_pnts[k++] = nxt_pnt; }
nxt_pnts.resize(k); hrz_offset.resize(k); vrt_offset.resize(k);
std::swap(prv_pnts, nxt_pnts); std::swap(prv_pyr, nxt_pyr);
if((int)prv_pnts.size() < min_num_pnts) { /* Активировать детектор или выполнить поиск точек заново */ continue; }
const double &avg_hrz_offset = calculateAverageOffset(hrz_offset); const double &avg_vrt_offset = calculateAverageOffset(vrt_offset); }
Особенность вышеприведённого цикла for(int i = 0; i < n; ++i) {...} в том, что он отсеивает те точки интереса, которые в силу различных условий перестали быть актуальными. Например по той причине, что алгоритм Лукаса-Канаде для каких-либо из них не смог провести соответствия между предыдущим и следующим кадром. Постепенно количество ранее обнаруженных точек будет уменьшаться и когда достигнет минимального значения min_num_pnts потребуется снова активировать детектор или выполнить поиск точек интереса заново.
Под конец цикла while(true) {...} вызывается функция calculateAverageOffset(), которая может просто вычислять среднее значение вектора, поданного ей на вход, либо, например, по пику в распределении Гаусса брать из вектора определённое значение.
Рассмотренный код функционирует на порядок быстрее, нежели если производить детекцию лица на каждом кадре. Однако у него имеются и отрицательные стороны. Голова - это трёхмерный объект, а значит сильные повороты и наклоны могут приводить к не вполне ожидаемым результатам. Также необходимо помнить о том, что оптический поток плохо работает на смещениях, скорость которых слишком высока по отношению к скорости видеозахвата. Иными словами, если объект будет резко мотать головой при стандартных 30 кадрах/сек, то трекинг собъётся и результат окажется неприемлемым.
Напоследок хочется добавить, что подход вовсе не ограничен применением одного только Лукаса-Канаде. Он в той же мере может быть использован, например, с алгоритмом Фарнебэка, реализация которого в OpenCV также имеется. Или, например, можно использовать трекинг по корреляции фазы, вопреки её традиционному использованию в основном в задачах стабилизации видео.

Как сократить регулярное выражение

Представим очень большую регулярку, которая в одной строке забирает все между тегами, например:
'>значение<'
Для этого напишем что-то вроде:
>([^<]+)
Подобных одинаковых абсолютно кусков выражения может быть много.
Можно ли заключить их в группу типа:
(?'value'[^<]+)
и использовать в другом куске этого же выражения по типу >(value)?


Ответ

Так как в в .NET нет \g и рекурсии, как в PCRE, невозможно внутри регулярного выражения использовать ссылку на часть регулярного выражения.
Для этого проще использовать string.Format()
var something = "[^<]*"; var regex = new Regex(string.Format(">{0}<.*?>{0}<", something));

Использование async/await в консольном приложении

Всем привет. Запутался немного в коде. Почему поток Main завершается до запуска этого кода ?
await Task.Factory.StartNew(() => { System.Threading.Thread.Sleep(4000); Console.WriteLine("Pavel"); });
Решил попробовать в Main приписать к вызову метода Math1 слово await но тогда код вообще не компилируется. А если его убрать, то выходит , что Main завершился мгновенно и дело не дошло до указанного выше блока кода. Привожу весь код
using System; using System.Threading.Tasks; class a { public async Task Meth1() { await Task.Factory.StartNew(() => { System.Threading.Thread.Sleep(4000); Console.WriteLine("Pavel"); }); } } class b { static void Main() { a A = new a(); await A.Meth1(); //без await сразу все завершается, с ним не компилится } }
Почему так происходит и как решить такую ситуацию ? Я ожидаю от кода такое поведение, что при вызове Meth1 Main ожидает пока в Meth1 выполнится лямбда


Ответ

Обновление. Начиная с C# 7.1, модификатор async можно использовать также и для функции Main. При этом неудобство, описанное ниже (отсутствует SynchronizationContext по умолчанию, а значит, код после await не будет возвращаться в исходный поток), остаётся.

Смотрите.
Если вы используете async/await, приложение командной строки — не лучший выбор. К сожалению, C# из коробки не поддерживает async для функции Main (обсуждение на гитхабе, вы можете тоже отписаться, чтобы было понятно, что эта фича нужна).
Поэтому вы должны писать что-то вроде такого:
class Program { static async Task AsyncMain(string[] args) { await Task.Factory.StartNew(() => { System.Threading.Thread.Sleep(4000); Console.WriteLine("Pavel"); }); }
static void Main(string[] args) { // синхронное ожидание! AsyncMain(args).Wait(); } }
Другая проблема состоит в том, что в приложениях командной строки нету SynchronizationContext'а, который мог бы «вернуть» выполнение в начальный поток. Потому что для этого нужен в той или иной форме аналог message loop'а, а у вас его нету. Таким образом, поведение программы будет отличаться от того, что обычно бывает в WPF/WinForms: код после await не будет возвращаться в исходный поток!
Как бороться с этим? Простейший обходной путь — можно тренироваться не на приложении командной строки, а на графическом приложении.
Более хороший путь — воспользоваться существующим message loop'ом. Например, так:
/* Обвязочный код для использования async/await в консольных приложениях на C# Создаёт SynchronizationContext, который возвращает async-вызовы в главный поток (в отличие от стандартного контекста, который бы использовался в консольных приложениях) Идея VladD, используйте и переделывайте как хотите. Никаких гарантий, разумеется. Требует подключения WindowsBase.dll */ class Program { static async Task AsyncMain(string[] args) { // тут стартует ваша программа, можете пользоваться async/await // не забудьте про return, например: return 0; }
[STAThread] static int Main(string[] args) { int result = -1; var dispatcher = Dispatcher.CurrentDispatcher; dispatcher.BeginInvoke((Action)(() => { AsyncMain(args).ContinueWith(asyncMain => { if (!asyncMain.IsCanceled && !asyncMain.IsFaulted) result = asyncMain.Result; dispatcher.BeginInvokeShutdown(DispatcherPriority.ApplicationIdle); }, TaskScheduler.FromCurrentSynchronizationContext()); })); Dispatcher.Run(); return result; } }

каждые 3 элемента через три

Добрый вечер всем. Есть родитель у него много детей

//green
//green
//green
//green
//green
//green
//green
//green //и т. д.

как с помощью css сделать так, чтоб каждые 3 элемента через три были зелеными?


Ответ

Я только это придумал
.child { display: block; height: 20px; width: 30px; background-color: #CCCCCC; margin: 2px; } .parent div:nth-child(6n-3), .parent div:nth-child(6n-4), .parent div:nth-child(6n-5) { background-color: #00CC00; }
Пример тут http://jsfiddle.net/046xsfLk/

Как создать рекурсивный запрос к БД с помощью Entity Framework?

Здравствуйте, у меня есть проблема. Есть таблица категорий, которая выглядит так:
Задача при выборе категории высшей иерархии подтянуть все его подкатегории - создать коллекцию категорий дерева. Вопрос такой: как реализовать такую задачу с помощью Entity Framework? Возможно ли сделать это одним запросом к БД?
За любую помощь буду признателен)


Ответ

Entity Framework не умеет в рекурсивные запросы. Но проблему решить можно.
Вариант 1:
Сделать view на основе рекурсивного запроса на SQL используя WITH CTE. После чего в коде вызывать получение данных из этой вью.
Примерный код SQL:
CREATE VIEW [dbo].[vw_Subcategories] AS WITH cte ( CategoryID, SubcatID) AS ( SELECT Id AS SubcatID, RootId as CategoryID FROM dbo.TableName UNION ALL SELECT e.Id AS SubcatID, cte.Id AS CategoryID FROM cte INNER JOIN dbo.TableName AS e ON e.RootId = cte.Id )
Вариант 2:
Сделать простой отдельный рекурсивный метод в коде для получения дочерних EF-объектов:
List GoDownRecursive(int categoryId) { var res = new List();
foreach(var subcategory in DbContext.Cateogires.Where(c => c.RootId == categoryId) { res.Add(subcategory); res.AddRange(GoDownRecursive(subcategory.Id)); }
return res; }
Запросов к базе будет больше, но если вложенность небольшая и запрос не самый частый, то вариант приемлимый. При желании полученные деревья можно кэшировать.

Способы передачи функции(функтора) в качестве аргумента другой функции

Наткнулся тут на вопрос про std::bind и возник вопрос.
Чем отличается способ с шаблоном
template void display( int a[], size_t n, Operation op ) // или Operation&& { for ( size_t i = 0; i < n; i++ ) { std::cout << op( a[i] ) << ' '; } std::cout << std::endl; }
от
void display( int a[], size_t n, std::function operation ) { //... }
и от
void display( int a[], size_t n, int operation( int ) ) {
}
Какие возможности и ограничения у того или иного способа, когда их нужно применять.


Ответ

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

В чем проблема со Stream?

Хочу преобразовать массив некоторых идентификаторов (все типа int) в список с некоторой попутной фильтрацией ( в список не нужно добавлять все идентификаторы).
Вот код:
ArrayList visitorsIdexes = Arrays.stream(targetVisitors) .filter(id -> checkVisitor(id, target.getTargetSegmentCube())) .map(id -> Integer.valueOf(id)) .collect(Collectors.toList());
Только оне не компилируется с такой проблемой:
Multiple markers at this line Type mismatch: cannot convert from Collector> to Supplier The method collect(Supplier, ObjIntConsumer, BiConsumer) in the type IntStream is not applicable for the arguments (Collector>)
Что-то в полном ступоре, почему не работает..


Ответ

Вы не преобразовали IntStream в Stream. По факту map(id -> Integer.valueOf(id)) ничего не делает, потому что map возвращает тот же IntStream. Чтобы преобразовать в объектный поток в общем случае нужен mapToObj, а в вашем конкретном проще всего написать boxed()
ArrayList visitorsIdexes = Arrays.stream(targetVisitors) .filter(id -> checkVisitor(id, target.getTargetSegmentCube())) .boxed() .collect(Collectors.toList());

Блокирование и разблокировка файла

Есть программа, которая перезаписывает некоторый файл. И есть другая программа, которая периодически считывает данные из файла. Однако, чтобы читающая программа всегда получала верные данные, нужно блокировать файл, пока он не запишется до конца. Есть такой код для записи файла с блокировкой:
int Writer() { int iErrorCode = 0; char pcStr[] = "I am string, that must be written to file.";
int iTry = 0; int iMaxTry = 10;
struct flock lck; lck.l_type = F_WRLCK; /*setting a write lock*/ lck.l_whence = 0; /*offset l_start from beginning of file*/ lck.l_start = 0l; lck.l_len = 0l; /*until the end of the file address space*/
int fd; /*file descriptor*/ fd = open("outfile.txt", O_RDWR); if (fd < 0) { perror("outfile.txt"); return 1; }
while (fcntl(fd, F_SETLK, &lck) < 0) { if (errno == EAGAIN || errno == EACCES) { if (++iTry < iMaxTry) { sleep(2); continue; } (void) fprintf(stderr, "File is bisy."); } }
size_t read_bytes; size_t written_bytes; size_t szContentLen = strlen(pcStr); char *buffer = new char[szContentLen]; strcat(buffer, pcStr); while ((read_bytes = read (fd, buffer, szContentLen)) > 0) { /* 1 == stdout */ written_bytes = write (1, buffer, read_bytes); if (written_bytes != read_bytes) { fprintf (stderr, "Cannot write
"); return 2; } } if (close (fd) != 0) { fprintf (stderr, "Cannot close file (descriptor=%d)
", fd); return 3; }
return iErrorCode; }
Как разблокировать данный файл после окончания записи, чтобы другая программа, которая захочет читать из файла, имела доступ к нему?


Ответ

Разблокировать файл после окончания записи можно так же, как вы его блокировали, только параметр в структуре поменять:
lck.l_type = F_UNLCK; /*unlock file */ lck.l_whence = 0; /*offset l_start from beginning of file*/ lck.l_start = 0l; lck.l_len = 0l; /*until the end of the file address space*/
fcntl(fd, F_SETLK, &lck);

Как через браузер выполнить команду в терминале Linux?

Есть какой-либо способ через адресную строку firefox выполнить команду в bash-e? Или запустить скрипт с параметрами. Например, в адресной строке я ввожу: run_script test1 и у меня запускается скрипт /usr/local/script.sh с параметром test1
У меня уже получилось запустить скрипт file:///usr/local/script.sh и в настройках firefox выбрать "все файлы *.sh открывать с помощью /bin/bash". А вот как мне передать этому скрипту переменные?


Ответ

можно воспользоваться каким-нибудь существующим незадействованным протоколом. список — на странице about:preferences#applications (или через меню preferences → applications).
например, протоколом irc. в колонке action напротив него откройте список и выберите use other, а в открывшемся диалоге укажите на созданный вами скрипт-обработчик.
теперь, если в браузере набрать irc://123&456?word/letter или «щёлкнуть» по ссылке с этим адресом (вроде нажмите сюда), то именно такую строку (irc://123&456?word/letter) ваш скрипт и получит первым параметром.
что дальше делать с этой строкой — уже на полное ваше усмотрение. можете, например, в какой-нибудь файл записывать:
#!/bin/bash echo "$1" >> /tmp/clicks.log
p.s. не забудьте биты исполняемости поставить на файл со скриптом:
$ chmod +x /путь/к/файлу

Функция mail в php

От кого придет сообщение, отправленное с помощью функции mail()? Нигде не могу найти об этом информацию.
В некоторых случаях отправителя дописывают в additional_headers, но ведь так можно и что угодно дописать, хоть barackobama@whitehouse.gov


Ответ

Если вы имеете ввиду отправителя письма, то оно будет таким, каким вы его укажите явно. Функция mail всего лишь передает вашему мейл серверу (скорее всего postfix) все данные, переданные вами в функцию.
Это всего лишь инструмент, который делает запрос на почтовый сервер адресата, а что вы там укажите это на вашей совести. Самое плохое, что может случится это черные списки и спам листы. Не забудьте так же про DKIM и SPF

Как в меню добавить сепаратор, если оно заполняется элементами от ICommand?

Придумал такую схему.
Создал класс
public class MyCommand : ICommand, ICollection
То есть каждая команда включает еще вложенные команды (вложенные меню)
В классе окна добавляю свойство
public MyCommand Menu { get; set; }
В дизайнере делаю так


И так же в ресурсы окна добавляю вот что

Все. В коде формирую дерево из MyCommand, и меню в окне создается автоматически по дереву. Класс MyCommand реализует слияние, так что я спокойно могу добавлять к основному меню дополнительные пункты (например меню, которое создано в контенте TabItem).
Все гениально и просто :), вот только я не знаю, как отделить пункты меню сепараторами. Я ведь не оперирую контейнерами (MenuItem), поэтому не могу просто взять и добавить new Separator(). Посоветуйте что нибудь для этого.


Ответ

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