Страницы

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

четверг, 25 октября 2018 г.

Что именно тяжелого в этих вычислениях?

Есть массив вида
ar=[283462197, 191777391, 243143621, 451231707, 217268739, ] // и там их 1 310 341 штук
нужно выделить уникальные значения, делаю через эту функцию
var uniqueAr = function(ar) { var existing = {}, result = []; var length = ar.length; for (i = length; i--;) { if (!existing.hasOwnProperty(ar[i])) { result.push(ar[i]); existing[ar[i]] = true; //any value will do } } return result;};
Работает имхо очень быстро за 80.774ms В итоге имею 114262 элементов, делаю свои дела и выясняется что из них нужно удалить 73928, и тут начинаются проблемы, я делаю так:
grdb.user_ids_clear//массив после уникализации banIds// те что нужно удалить, само собой тоже уникальны console.time("исключение банов"); var tar = []; var exist = false; var banIdslength = banIds.length; for (let i = grdb.user_ids_clear.length; i--;) { exist = false; for (let ii = banIdslength; ii--;) { if (banIds[ii] === grdb.user_ids_clear[i]) { exist = true; break; } } if (!exist) tar.push(grdb.user_ids_clear[i]); } console.timeEnd("исключение банов");
И это заняло 893288.239мс это просто неприемлемо, прощу объяснить как так выходит, почему уникализация процедура той же сложности делается на 4 порядка быстрее с размером в 10 раз большим массивом.


Ответ

В первом случае вы используете хеш-таблицу, которой являются любые большие объекты. У вас всего один проход по массиву, и время работы пропорционально размеру массива.
Во втором случае вы каждый раз используете линейный поиск по массиву - а потому время работы оказывается пропорционально произведению длин массивов.
Вам в этой задаче нельзя использовать линейный поиск. Вместо этого нужно преобразовать второй массив в хеш-таблицу так же как это делалось при поиске уникальных записей. А уже потом делать по этой таблице поиск.
const bansSet = {}; for (let ii = banIdslength; ii--;) { bansSet[banIds[ii]] = true; } for (let i = grdb.user_ids_clear.length; i--;) { const exist = bansSet.hasOwnProperty(grdb.user_ids_clear[i]); // ... }
PS все-таки рекомендую использовать Set или Map вместо объектов - на современных браузерах они должны работать шустрее:
const bansSet = new Set(banIds); for (let i = grdb.user_ids_clear.length; i--;) { const exist = bansSet.has(grdb.user_ids_clear[i]); // ... }

function - Смысл флага deterministic

В чём разница между детерменированной и недетерминированной функцией? Я надеялся, что deterministic заставит СУБД посчитать функцию чистой и закеширует её результат?
The DETERMINISTIC clause for functions is ideal for functions that do not have any non-deterministic components. This means that each time you provide the function with the same parameter values, the result is the same. When you define a function you can simply add the DETERMINISTIC option to the declaration section, making sure that the function (or any functions or procedures it calls) does not depend on the state of session variables or schema objects as the results may vary across invocations. This option instructs the optimizer that it may use a cached result whenever it encounters a previously calculated result. Source
create function det() returns INTEGER DETERMINISTIC NO SQL return @param;
create function ndet() returns INTEGER NOT DETERMINISTIC NO SQL return @param;
select @param:=5, det() d1, ndet() n1 , @param:=3, det() d2, ndet() n2 , @param:=1, det() d3, ndet() n3 , @param:=7, det() d4, ndet() n4;
Результат:
5, 5, 5, 3, 3, 3, 1, 1, 1, 7, 7, 7
Т.е. я не вижу никакой разницы.
Как понять, в чём разница, и в каких ситуациях она проявляется?


Ответ

Если вы определяете DETERMINISTIC, это значит, что для одних и тех же параметров функция всегда возвращает одно и то же значение. Соответственно, MySQL по-идее может кешировать значение, чтобы не пересчитывать его для одних и тех же параметров.
Но поддержка DETERMINISTIC в MySQL реализована не полностью, функция будет выполняться всегда.
Пример на MySQL 5.7.22:
create function rr() returns INTEGER DETERMINISTIC return RAND()*1000; select rr(), rr(); +------+------+ | rr() | rr() | +------+------+ | 300 | 451 | +------+------+
Во WHERE выполняется 1 раз:
CREATE FUNCTION r1() returns INTEGER DETERMINISTIC return RAND()*3;
SELECT * FROM ( SELECT 1 AS ID UNION ALL SELECT 2 AS ID UNION ALL SELECT 3 AS ID UNION ALL SELECT 4 AS ID UNION ALL SELECT 5 AS ID ) AS t1 WHERE r1() < ID;
Выведет, например, 1 | 2 | 3, то есть без "выпадов".

Существует ли возможность создавать объект определенного типа, без использования класса Activator? [дубликат]

На данный вопрос уже ответили: Способы создания объектов в C# 2 ответа Для приведения типов наследуемого объекта написана функция. Есть-ли какая-либо возможность создать объект нужного типа без использования класса Activator?
public T ToObject() { var o = Activator.CreateInstance(typeof(T)); ... return (T)o }


Ответ

Я написал простой тест для BenchmarkDotNet
[MemoryDiagnoser] public class Creator { public class A { }
[Benchmark] public A ExplicitCtor() { return new A(); }
[Benchmark] public A WithActivator() { return Activator.CreateInstance(); }
[Benchmark] public A WithReflection() { return (A)typeof(A).GetConstructor(new Type[0]).Invoke(new object[0]); }
ConstructorInfo ctor; [Benchmark] public A WithReflectionCached() { if (ctor == null) ctor = typeof(A).GetConstructor(new Type[0]); return (A)ctor.Invoke(new object[0]); }
Func
lambda; [Benchmark] public A WithLambla() { if (lambda == null) lambda = Expression.Lambda>(Expression.New(typeof(A)), Array.Empty()).Compile(); return lambda(); }
[Benchmark] public A WithCustomActivator() { return CustomActivator.CreateInstance
(); } }
(CustomActivator by Sergey Teplyakov можно взять здесь)
Результаты получились следующие:
| Method | Mean | Error | StdDev | Median | Gen 0 | Allocated | |--------------------- |-----------:|----------:|----------:|-----------:|-------:|----------:| | ExplicitCtor | 2.591 ns | 0.0523 ns | 0.0489 ns | 2.582 ns | 0.0076 | 12 B | | WithActivator | 113.661 ns | 0.4652 ns | 0.3885 ns | 113.583 ns | 0.0074 | 12 B | | WithReflection | 369.719 ns | 6.9477 ns | 5.4243 ns | 367.856 ns | 0.0229 | 36 B | | WithReflectionCached | 281.290 ns | 0.9358 ns | 0.7814 ns | 281.415 ns | 0.0148 | 24 B | | WithLambla | 17.391 ns | 0.0700 ns | 0.0621 ns | 17.373 ns | 0.0076 | 12 B | | WithCustomActivator | 27.644 ns | 0.6665 ns | 1.3155 ns | 27.039 ns | 0.0076 | 12 B |
Т.е. что мы видим: рефлексия очень медленная и даже кеширование конструктора не сильно помогает, создание объекта с помощью Activator быстрее явной рефлексии в 2,5-3 раза, но всё еще сильно медленнее явного вызова конструктора (в 40 раз!), наиболее эффективный метод, как и ожидалось — создание и кеширование делегата, создающего объекты, он всего в ~6 раз медленнее явного вызова конструктора (тут, подозреваю, медленное именно создание делегата, а сам его вызов не должен уступать явному вызову конструктора, т.е. чем больше объектов мы будем создавать, тем ближе будет средняя скорость к идеальной).
Таким образом, имеет смысл переписать ваш метод во что-то вроде такого:
Dictionary cache = new Dictionary(); public T Create() { if (!cache.TryGetValue(typeof(T), out var d)) d = cache[typeof(T)] = Expression.Lambda>( Expression.New(typeof(T)), Array.Empty()) .Compile(); return ((Func)d)(); }

C# Хеш от строки, нужен алгоритм

В C# у типа string есть метод GetHashCode() возвращающий хеш значение типа int. Этот метод на разных версия платформы .Net Framework возвращает разное значение. Для моей задачи требуется, чтобы возвращаемое значение было одинаковое на разных платформах. Нужен алгоритм вычисления хеша строки возвращающий int. Может кто-нибудь предложить такой алгоритм?
Уточнения:
Без использования unsafe кода. Весь диапазон int (положительные и отрицательные числа) Входная строка небольшая.


Ответ

Можно взять любую реализацию String.GetHashCode и использовать ее, вот переписанные без unsafe 2 версии. Можете убедиться, что StringHashCode40 возвращает тоже самое, что и нативный GetHashCode
public static int StringHashCode20(string value) { int num = 352654597; int num2 = num;
for (int i = 0; i < value.Length; i += 4) { int ptr0 = value[i] << 16; if (i + 1 < value.Length) ptr0 |= value[i + 1];
num = (num << 5) + num + (num >> 27) ^ ptr0;
if (i + 2 < value.Length) { int ptr1 = value[i + 2] << 16; if (i + 3 < value.Length) ptr1 |= value[i + 3]; num2 = (num2 << 5) + num2 + (num2 >> 27) ^ ptr1; } }
return num + num2 * 1566083941; }
public static int StringHashCode40(string value) { int num = 5381; int num2 = num; for (int i = 0; i < value.Length; i += 2) { num = (((num << 5) + num) ^ value[i]);
if (i + 1 < value.Length) num2 = (((num2 << 5) + num2) ^ value[i + 1]); } return num + num2 * 1566083941; }
static void Main(string[] args) { string value = "123"; Console.WriteLine(StringHashCode20(value)); Console.WriteLine(StringHashCode40(value)); Console.WriteLine(value.GetHashCode()); }

Как программно экранировать управляющие символы в строке?

Мне необходимо вставить в паттерн регулярного выражения:
$@"^(?:[^\p{{L}}]|[{exclusion}])+$" //Цель: Запретить использование каких либо букв в строке, кроме тех что заданы в переменной - exclusion
строковую переменную:
string exclusion;
в которой все управляющие символы были бы экранированы, что позволило бы избежать ошибок связанных с работой регулярного выражения.
Я нашел метод Regex.Escape(). Но он не удовлетворяет моим потребностям. Например, если значение exclusion = @"[text]" передать в метод Regex.Escape() то он вернет строку "\\[text]". После вставки данной строки в паттерн вместо переменно exclusion:
$@"^(?:[^\p{{L}}]|[{exclusion}])+$" //Цель: запретить использование каких либо букв в строке, кроме тех что заданы в переменной - exclusion
он приобретает следующий вид:
$@"^(?:[^\p{{L}}]|[\[text]])+$"
В результате регулярное выражение работает неправильно. Подозреваю, что причина в лишнем символе - ]
Скажите пожалуйста как экранировать все управляющие символы в строке? Есть ли какой то другой способ кроме метода - Regex.Escape()? Может быть я его как то неправильно использовал и не замечаю своей ошибки?


Ответ

Regex.Escape экранирует те знаки, которые считаются специальными вне символьных классов:
Escapes a minimal set of characters (\, *, +, ?, |, {, [, (, ), ^, $, , #, and white space) by replacing them with their escape codes. (Экранирует минимальный набор знаков (\, *, +, ?, |, {, [, (, ), ^, $, , # и пробельный символ) путём замены на их escape-коды)
На самом деле, внутри символьных классов специальными считаются только следующие символы:
^ - может означать исклбчающий тип символьного класса, если находится сразу после открывающей [ ] - закрывает символьный класс \ - экранирует специальные символы - - задаёт диапазон символов или "вычитание символьных классов"
Для экранирования этих знаков достаточно использовать
exclusion.Replace("\\", @"\\").Replace("^", @"\^").Replace("-", @"\-").Replace("]", @"\]")
или
Regex.Replace(exclusion, @"[]^\\-]", "\\$&")
Решение:
var pattern = $@"^(?:[^\p{{L}}]|[{Regex.Replace(exclusion, @"[]^\\-]", "\\$&")}])+$";
Или (так как [^\p{L}] = \P{L}):
var pattern2 = $@"^[\P{{L}}{Regex.Replace(exclusion, @"[]^\\-]", "\\$&")}]+$";

Типичные ошибки программирования на Objective-C [закрыт]

Расскажите общие ошибки, допущенные Objective-C разработчиками, которые вы знаете. Как мы можем их избежать? В общем, хотелось бы увидеть ошибки связанные с управлением памятью, анти-паттерны и любые другие ошибки программирования под iOS. Пожалуйста, обоснуйте свой ответ, а также можно привести примеры. Начну с одной известной ошибки. Это объявление нового класса без суперкласса, т.е. предполагая, что он будет иметь суперкласс по умолчанию. Здесь важно помнить, что Objective-c не поддерживает множественное наследование, НО поддерживает несколько корней. То есть корень - это не обязательно только класс NSObject. Таким образом, если вы пишете /* не имеет суперкласса, не делайте этого! */ @interface MyClass @end Вы объявляете новый корень, а не подкласс NSObject. Все подклассы NSObject должны быть прописаны вот так: /* суперкласс NSObject */ @interface MyClass : NSObject @end


Ответ

UIViews и UIViewControllers - разные вещи и не могут быть взаимозаменяемыми. Не каждый контроллер должен быть UIViewController. Жизненный цикл UIViewController. В частности вьюшка выгружается (unloaded) в ответ на memory warnings. Обычно это бывает, когда разработчик использует вьюшку для хранения данных. Результат - потеря данных.

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

Некоторые компоненты слабо связанного кода находятся в одной сборке. Хотелось бы контролировать отсутствие между ними циклических ссылок на этапе компиляции, не разбивая сборку. Наиболее логичным решением выглядит использование нескольких проектов сборок, которые потом компилируются в одну сборку. Циклические ссылки предотвращаются стандартным механизмом работы проектов, а сборка сливается.
Есть ли такая технология для Microsoft Visual Studio?


Ответ

Вы можете попробовать компилировать не в целую сборку (.dll), а в объектный файл (.netmodule). Для этого нужно или строить при помощи msbuild, либо открыть файл проекта вручную, найти строку вида Library и поменять её на Module. (Учтите, компиляция этого через Visual Studio считается неподдерживаемым сценарием. Но у меня работало.)
Затем, для компоновки модулей в assembly вам нужно вручную вызвать компоновщик. Например, в каком-либо post-build step'е:
call "%VS120COMNTOOLS%vsvars32.bat" set M1=$(SolutionDir)Module\$(OutDir)Module.netmodule set M1PDB=$(SolutionDir)Module\$(OutDir)Module.pdb set M2=$(SolutionDir)Main\$(OutDir)Main.netmodule set ENTRY=Main.Program.Main link /ltcg /assemblymodule:"%M1%" "%M2%" /entry:%ENTRY% /subsystem:CONSOLE /out:"$(SolutionDir)Program.exe" /debug copy /b %M1% "$(SolutionDir)" copy /b %M1PDB% "$(SolutionDir)"
Разумеется, вам придётся подставить нужные пути вручную.
Вот большое исследование по теме вопроса.
(Уверен, это всё можно автоматизировать при помощи msbuild, но я не знаю, как именно.)

CSS height в % не работает?

Почему, когда в height пишешь в px всё нормально, а когда в процентах, как на рисунке, ничего не работает? height в процентах нельзя делать?
School.ua


Ответ

Если вы берете проценты, их нужно брать от чего то Т.е. либо пропишите, как сказано выше body, html{height:100%} либо укажите в родительском элементе тоже самое body.style_body { height:100%}

Как при помощи canvas сделать картинку круглой?

Здравствуйте. Как при помощи HTML5, canvas и JavaScript загрузить картинку и сделать ее круглой (без искажения изображения, просто обрезать края и закруглить)? PS Без использования каких-либо библиотек.


Ответ

В HTML5 при помощи canvas, закруглить картинку оказалось немного сложнее, чем я предполагал. Шарясь по гуглу, у меня возникло ощущение, что при помощи canvas, все обычно только чертят всякие там градиенты, линии, кружочки и т.д. Потому что другого очень мало. И то, как сделать круглой картинку, я догадался только прочитав пару глав из книги Дронов.В - HTML 5 CSS 3 и Web 2.0...... Ну так вот, приведу пример, где генерируется data url итоговой картинки, которую впредь можно ставить куда угодно.


Вот что в итоге получится после одного нажатия на нашу картинку:

И еще. Из-за какой-то там политики безопасности, метод "toDataURL()", будет работать только в текущем домене. Ну и у меня почему-то не работает на локальном компьютере.

Облачное хранилище с неограниченным трафиком

Здравствуйте. Знаете ли вы какой-нибудь сервис облачного хранения данных, типа DropBox, но только с неограниченным трафиком? DropBox сильно ограничивает пропускную способность канала , и, если ссылки собирают много трафика, то DropBox просто-напросто ставит бан на аккаунт. При каждой последующей попытке доступа к определенному файлу через ссылку DropBox будет выдавать 509-ую ошибку( BandWidth Error ). Поэтому, хотелось бы найти похожий сервис, но с неограниченным трафиком. Желательно с прямыми ссылками и желательно без файловых помоек. P.S Если такое вообще существует, за бесплатно. =)


Ответ

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

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

Здравствуйте! В переменной есть текст, в котором нужно найти информацию. Я планирую это сделать с помощью регулярных выражений. Столкнулся с проблемой при написании на Си. Заголовочный файл в MS VS 2010 отсутствует, есть файл , но работать с ним нельзя, так как он предназначен для C++, а я пишу на C(Си). Подскажите, есть какая-то альтернативная библиотека/заголовочный файл или способ установки файла в VS? Спасибо! PS Я так уперто пишу на Си, так как хочу перейти потом на objective-c. Или можно спокойно переходить на C++, так как это не повлечёт проблем при написании на objective-c? Или я ошибаюсь? ЗЗЫ Уважаемый @ХэшКод, подскажите, пожалуйста, почему у меня пропала кнопка "добавить комментарий" - я не могу ответить на вопросы?


Ответ

Кроссплатформенный подход - это использовать PRCE В стандарте ANSI C нет регулярных выражений. В GCC есть поддержка регулярных выражений: Regular Expression Matching - это тот regex.h, который был упомянут. В Visual C++ при необходимости работы с регулярными выражениями подключают CAtlRegExp (код выносят в исходник на C++).

Прогресс бар загрузки файла на сервер

Подскажите, пожалуйста, реализацию прогресс бара (не флэш). Желательно на примере показать, самый что не наесть простейший пример. Спасибо!


Ответ

Лучше чем FancyUpload пока не встречал! Рекомендую поковырять и использовать! Очень легко устанавливается, а также очень много плюшек...

Время срабатывания таймера

1. function fn(){ alert(new Date().getTime()-last); } var last=new Date().getTime(); setTimeout(fn,200)// FF ,IE8, Сhrome около 200
2. function fn(){ alert(new Date().getTime()-last); } var last=new Date().getTime(); setTimeout(fn,200);//ie8 1125 FF 208 Chrome 203 for(var i=0;i<1000000;i++){ var j=j+1; } Как написано в одной книге ,через 200мс функция в интервале будет добавлена в очередь , а не сработает.Это задание будет ожидать очереди выполнения ,пока не будут выполнены все функции находящиеся в этой очереди до этого. Так вот меня интересует это что IE8 ждет пока не выполнится цикл а потом только запускаетсяба остальные не ждут выполнения цикла?


Ответ

JS, на уровне программиста, работает в одном потоке, даже если вы задали точный таймер, но, в этот момент времени, у вас занят поток, таймер, естественно, выполнен не будет, вернее будет выполнен с "опозданием". Если вам интересно почему у IE настолько плохие результаты, то, если без грязных слов, реализация JS в нем - не очень. Вообще меня удивляет то, что можно этого не знать, любая книга по JS, даже из разряда - "выучи за 2 недели" об этом упоминает. Специально для неверующего тов. @Чад 'а, открываем chrome, вставляем в консоль и выполняем: console.time('timer'); setTimeout(function() { console.timeEnd('timer') }, 200); for( var i=0; i<1000000; ++i ) { // .... } // у меня 2274ms смотрим, понимаем что я был прав, ставим плюсик

Рассылка по e-mail в высоконагруженном проекте

Добрый день, задача следующая: Имеется сайт на котором проходит порядка 5 регистраций в секунду. Всем зарегистрировавшимся необходимо отправить сообщение по e-mail с ссылкой подтверждения. В наличии: свой SMTP-сервер, PHP, MySQL Мое виденье данного процесса следующие: Обрабатываем регистрации пользователей, заносим в БД ключ подтверждения, наряду с остальными данными пользователя. Потом раз к примеру в секунд 10 выберем свежеиспечённых юзеров по наличию этого ключа, И рассылаем сообщения по SMTP (по сокету, перечисляя в запросе получателей). При подтверждении ключ затираем, registration is completed! Хотелось бы услышать мнения и рекомендации для оптимизации данного подхода, а так же возможные пути решения задачи.


Ответ

Я обычно делаю три поля: КлючПотверждения, НовыйПароль, БылоЛиПисьмо. Объясняю зачем. Для нового пользователя в поле Пароль ставится "", заполняется НовыйПароль, БылоЛиПисьмо* = 0. Отправлялка делает запрос везде, где БылоЛиПисьмо = 0. И для них сразу делает апдейт БылоЛиПисьмо = 1. После успешной отправки письма, делается БылоЛиПисьмо = 2. Если была ошибка отправки - БылоЛиПисьмо = 3, или письмо вернулось с отлупом БылоЛиПисьмо = 4 (мониторится по РОРу). Эта таблица периодическим кем-то мониторится, чистится. БылоЛиПисьмо == 3 раз в несколько часов отправляется, пока не пройдут сутки с момент регистрации, потом ставится как отлуп. При нажатии ссылки с ключем -> Пароль = НовыйПароль. КлючПотверждения = пусто, НовыйПароль = пусто. При сбросе пароля заполняется НовыйПароль и КлючПотверждения Если в БД Пароль = "*" пишем пользователю, что учетка не активирована.

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

В общем, для чего всё это нужно: есть почти полностью реализованный эмулятор CHIP8. Оперативная память у него состоит из ячеек, размером в 1 байт, и предоставляет диапазон адресов от 000h до FFFh. Я её объявил как:
unsigned char memory[0x1000];
Видеопамять же находится в той же оперативной памяти с некоторым смещением, и занимает диапазон от F00h до FFFh.
Если к оперативной памяти удобно обращаться как к одномерному массиву, то к видеопамяти удобнее обращаться как к двумерному массиву типа bool[][] (потому, что дисплей монохромный, и его пиксели имеют два состояния — "чёрный" и "белый").
Как правильно и безопасно получить указатель на двумерный массив [32][64] из указателя на одномерный? Одномерный же массив получить легко:
bool *videomem = (bool *)memory + 0xF00;
А вот двумерный массив уже не получается:
bool *video_mem[64] = (bool *[64])memory + 0xF00;
Можно, конечно, создавать для видеопамяти отдельный массив (и многие программы адекватно работают), но это снижает точность эмуляции (некоторые программы могут писать напрямую в видеопамять CHIP8).


Ответ

Попробуйте так: unsigned char memory[0x1000];
const size_t video_mem_row_size = 64; // или 0x40, раз уж всё в hex const size_t video_mem_offset = 0xF00; typedef unsigned char video_mem_row[video_mem_row_size];
video_mem_row* video_mem = (video_mem_row*)(memory + video_mem_offset); Проверка: http://ideone.com/mpflzb Если у вас 64 — это размер в битах, и вы оперируете битами, вам, судя по всему, понадобится немного другой код. unsigned char memory[0x1000] = {}; // обязательно инициализируйте!
const size_t bits_in_byte = 8; const size_t video_mem_offset = 0xF00;
const size_t video_mem_row_bitsize = 0x40; const size_t video_mem_row_stride = (video_mem_row_bitsize + (bits_in_byte - 1)) / bits_in_byte;
typedef unsigned char video_mem_row[video_mem_row_stride];
video_mem_row* video_mem = (video_mem_row*)(memory + video_mem_offset);
const size_t video_mem_number_of_rows = 0x20;
bool get_video_bit(size_t row, size_t col) { if (row >= video_mem_number_of_rows || col >= video_mem_row_bitsize) throw std::invalid_argument("index"); unsigned char* p = &video_mem[row][col / bits_in_byte]; unsigned char mask = ((unsigned char)1) << col % bits_in_byte; return *p & mask; }
void set_video_bit(size_t row, size_t col, bool value) { if (row >= video_mem_number_of_rows || col >= video_mem_row_bitsize) throw std::invalid_argument("index"); unsigned char* p = &video_mem[row][col / bits_in_byte]; unsigned char mask = ((unsigned char)1) << col % bits_in_byte; if (value) *p |= mask; else *p &= ~mask; } Проверка: http://ideone.com/2BBcM1 Я бы посоветовал обернуть это в класс. Если хотите, можно написать индексаторы в духе std::vector

Тернарная операция ? : Как работает?

Пишу я, значит, лабу - надо организовать двойную очередь шаблонным классом и продемонстрировать работу в main() - и тут до меня доходит, что я не знаю, как работает тернарная операция ?: template const TInfo& TDeque::GetFront() const { return front ? front->info : 0; } Когда вызывал этот метод из main() для своего класса Man, то вызывался конструктор копирования последнего в строчке return front ? front->info : 0; , а потом ещё и деструктор! В результате программа вылетала (ну не должно было там ничего вызываться!). Но ведь возвращаю я по ссылке!!! После двухчасового безрезультатного поиска ошибок данную функцию переписал: template const TInfo& TDeque::GetFront() const { if(front) return front->info; return 0; } И всё работает!!! Никакие конструкторы/деструкторы не вызываются! В чём отличие и почему первая так странно себя вела?


Ответ

В первом случае вызывается конструктор копирования TInfo(front->info) или конструктор TInfo(0) - тернарной операции надо второе и третье выражения обязательно привести к одному типу, если это возможно. Она это и делает. Поэтому получается, что возвращается ссылка на временный анонимный стековый объект в любом случае, даже вместо front->info. Во втором случае необходимость создания анонимного экземпляра возникает только в return 0; , что оказывается эквивалентно return TInfo(0); . В обоих случаях, видимо, не выдается предупреждение, т.к. возвращается const TInfo&. UPD: "видимо" - потому что не компилировал, нет сейчас возможности.

Асинхронный Tcp клиент-сервер

Помогите, пожалуйста, с пониманием асинхронной реализации Tcp клиент-сервера. Читал статьи на MDSN, гуглил. Но эта куча BeginWrite, BeginRead, коллбэков просто выносит мозг. Правда ли то, что несмотря на задающийся размер буфера в BeginRead, могут прийти меньше или больше данных? И как тогда с этим справляться? Как вообще эффективно реализовать простейший клиент-сервер, если первыми двумя байтами идет "код действия", а затем произвольное кол-во байт, в которых содержатся строки, int, ushort и т.д., если часть пакета может где-то застрять или прийти излишек? С синхронной реализацией все ок, но ест много ЦП т.к. цикл while.


Ответ

Сейчас принято делать всю асинхронность через async/await. Вот несколько примеров: [1], [2], я надёргаю кусков из них.
Сервер слушает входящие сообщения, и при приходе запускает на обработку. Обработка бежит параллельно, а сервер продолжает слушать дальше в цикле (AcceptTcpClientAsync() и дальше). Получится что-то такое:
Весь сервер:
void RunServer() { var tcpListener = TcpListener.Create(<порт>); tcpListener.Start(); while (true) // тут какое-то разумное условие выхода { var tcpClient = await tcpListener.AcceptTcpClientAsync(); processClientTearOff(tcpClient); // await не нужен } }
async Task processClientTearOff(TcpClient c) { using (var client = new Client(c)) await client.ProcessAsync(); }
Обработчик одного клиентского запроса:
class Client : IDisposable { NetworkStream s;
public Client(TcpClient c) { s = client.GetStream(); }
public void Dispose() { s.Dispose(); }
async Task ReadFromStreamAsync(int nbytes) { var buf = new byte[nbytes]; var readpos = 0; while (readpos < nbytes) readpos += await s.ReadAsync(buf, readpos, nbytes - readpos); return buf; }
public async Task ProcessAsync() { var actionBuffer = await ReadFromStreamAsync(2); var action = (ActionEnum)BitConverter.ToInt16(actionBuffer, 0); switch (action) { // логика в зависимости от кода команды } } }
Если сервер надо останавливать, вам придётся дождаться окончания работы запущенных Task'ов:
async void RunServer() { var tcpListener = TcpListener.Create(<порт>); tcpListener.Start(); while (можно продолжать) { var tcpClient = await tcpListener.AcceptTcpClientAsync(); processClient(tcpClient); // await не нужен } await Task.WaitAll(activeClientTasks.ToList()); // нужна копия }
HashSet activeClientTasks = new HashSet(); async Task processClient(TcpClient c) { using (var client = new Client(c)) { Task task = null; try { task = client.ProcessAsync(); activeClientTasks.Add(task); await task; } finally { if (task != null) activeClientTasks.Remove(task); } } }

Вот реализация таймаута (набросал, код не запускал, возможны ошибки):
async Task ReadFromStreamAsync(int nbytes, CancellationToken ct) { var buf = new byte[nbytes]; var readpos = 0; while (readpos < nbytes) readpos += await s.ReadAsync(buf, readpos, nbytes - readpos, ct); return buf; }
async Task ReadWithTimeout(int n) { using (var cts = new CancellationTokenSource()) { var readTask = ReadFromStreamAsync(n, cts.Token); var timeoutTask = Task.Delay(1000); await Task.WhenAny(readTask, timeoutTask); if (!readTask.IsCompleted) { cts.Cancel(); // cancel read task return null; } else { var bytes = readTask.Result; return Decode(bytes); } } }

Обновление:
Следуя совету @Pavel Mayorov, последний метод можно переписать проще и изящнее:
async Task ReadWithTimeout(int n) // (*) { using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1000))) { try { return Decode(await ReadFromStreamAsync(n, cts.Token)); } catch (OperationCanceledException) { return null; } } }

Обновление:
К сожалению, несмотря свою изящность, метод с обрывом чтения (я имею в виду вариант, обозначенный (*)) не работает из-за бага в BCL. Я попробую уточнить код. Кажется, хорошей идеей является закрыть клиент полностью, в соответствии со старой семантикой WinAPI. Вот сообщение на Microsoft Connect, проголосуйте за исправление!

Обновление: Поправил код, руководствуясь предыдущим обновлением. Теперь при обрыве по таймауту возвращается не null, а бросается TimeoutException (после которого клиент нужно закрывать).
async Task ReadWithTimeout(int n) { using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1000))) { var token = cts.Token; try { // при обрыве ожидания по токену закрываем клиент // с выбросом ObjectDisposedException using (token.Register(client.Close)) return Decode(await ReadFromStreamAsync(n, cts.Token)); } catch (ObjectDisposedException) when (token.IsCancellationRequested) { throw new TimeoutException(); } } }

Перенос InnoDB таблиц как файлов

Известно, что MySQL таблицы MyISAM хранит в виде трёх файлов: tbl_name.frm - описание структуры таблицы, tbl_name.myd (myData) - данные, хранящиеся в таблице, tbl_name.myi (myIndex) - индексы. Если MySQL сервер остановить, то путём простого копирования этих файлов можно перенести таблицу на другой сервер. Это иногда намного удобнее и быстрее, чем сдампить таблицу на одном сервере и залить дамп на другом.
Вопрос - как проделать этот трюк для таблиц InnoDB? Таблицы там живут в файле (файлах) ibdata*, перенести его можно только целиком?


Ответ

Из коробки InnoDB хранит все таблицы в общем пуле ibdata и описанный в вопросе трюк невозможен. Однако, если MySQL сервер настроен на использование file-per-table tablespaces, для каждой таблицы будет создаваться отдельная пара файлов (вида tbl_name.frm - структура и tbl_name.ibd - даныне и индексы). Помимо описанного трюка, это даёт другие преимущества, вроде быстрого выполнения запросов TRUNCATE TABLE и возможности получить обратно дисковое пространство, занятое таблицей, при её удалении (в случае использования ibdata* дисковое пространство при удалении таблиц не освобождается). Настройка выглядит так (в my.cnf):
[mysqld] innodb_file_per_table=1
При остановленном MySQL сервере файлы .frm и .ibd можно копировать и переносить, как и в случае MyISAM, а если нужно скопировать таким образом таблицу, не останавливая сервер, нужно прибегнуть к хитрости - сбросить на диск кеш и "выгрузить" таблицу (таблицы), которые хотим скопировать:
FLUSH TABLES table_one, table_two FOR EXPORT;
Теперь файлы .frm и .ibd можно копировать на лету - разумеется, с момента FLUSH до окончания копирования работать с данной таблицей нельзя (но можно с остальными).
"Подключение" перенесённой на другой сервер таблицы InnoDB выглядит так:
Создаём на новом месте в базе с таким же именем (это важно), как у базы, в которой находилась переносящаяся таблица, таблицу с такой же структурой, как переносящаяся (пустую) Выполняем
ALTER TABLE tbl_name DISCARD TABLESPACE; Подкладываем скопированные файлы tbl_name.frm и tbl_name.ibd Выполняем
ALTER TABLE tbl_name IMPORT TABLESPACE;
Вуаля, таблица перенесена!
Перед тем, как впервые воспользоваться этой инструкцией для операций с живыми данными, потренируйтесь на чём-нибудь тестовом, что не жалко испортить. И всегда делайте бекапы!

MVVM, Shared Model и паттерн Repository

Имеется WPF MVVM приложение, отображающее геометрические фигуры (Shape) внутри полотна (Canvas).
Упрощенная версия для простоты изложения:
Модель:
class Canvas { public List Shapes; }
class Shape { public int X; public int Y; }
Имеется несколько ViewModel'ей, некоторые из них отображают данные выбранной фигуры (фигура выбирается по клику на фигуру), некоторые - данные выбранного Canvas'а (выбирается с помощью комбобокса в ToolbarView), некоторые - и то и другое.
Т.о. имеется CanvasViewModel, CanvasPropertiesViewModel, ShapePropertiesViewModel , ToolbarViewModel.
ToolbarViewModel, CanvasViewModel и CanvasPropertiesViewModel связаны с текущим Canvas'ом. ToolbarViewModel и ShapePropertiesViewModel связаны с выбранной фигурой. ToolbarView, связанный с ToolbarViewModel, отображает большой плоский список названий всех canvas'ов.
Вопрос 1: как шарить между ViewModel'ми выбранную фигуру и выбранный canvas? Пробовал через EventAggregator, но получается слишком много регистраций сообщений, код становится не читаемый.
Вопрос 2: Кто должен отвечать за загрузку данных с сервера о canvas и его сохранение? И где лучше разместить эту логику (может как-то использовать Repository)? (имеется сторонний web сервис, который отдает и сохраняет данные о canvas)


Ответ

Во-первых, если Canvas ещё как-то оправдано, то ToolbarViewModel — никак. Тулбар — это подробность View, а смысл этой VM — корневые параметры отображения.
Таким образом, у нас получается class RootVM с ReadOnlyCollection Canvases и DP CurrentCanvas. К которому легко прицепить комбобокс или там ListView
Затем, я бы слил вместе CanvasViewModel и CanvasPropertiesViewModel, вроде бы они отвечают за одну и ту же сущность.
Давайте посмотрим, кому из ваших VM реально нужен CurrentCanvas. ToolbarViewModel содержит его. CanvasViewModel существует на каждый канвас, и знать о CurrentCanvas вовсе не должна. И CanvasPropertiesViewModel мы слили с CanvasViewModel
Проблема исчезла!

Теперь, о загрузке/выгрузке с сервера. За это отвечают модельные объекты (по классу на Canvas и фигуру). Решение о загрузке-выгрузке принимает в любом случае бизнес-логика, так что это она должна командовать модели произвести обмен информацией. Ну и на VM лежит ответственность за синхронизацию данных с моделью.

Не бойтесь, чтобы одна VM отображалась в нескольких местах несколькими разными View, причём по-разному. Это нормальная практика.

Как реализовать быстрое подключение к БД для живого поиска?

Здравствуйте!
Я собираюсь сделать на сайте живой поиск (как в Google). Нашел достаточно много материалов на эту тему. Лишь из-за одного момента я не могу приступить. Мой уровень знаний достаточно мал и я не могу понять как мне решить следующую проблему:
Вот с сайта, при помощи Ajax поступает запрос на .php скрипт, который должен взять из базы инфу. Вопрос - как можно быстро подключиться к бд или вообще сделать это заранее? Объяснений я не нашел. Я так понял, что больше всего времени тратиться именно на подключение к бд. Подключаться к ней после ввода каждого символа не получится. Все будет виснуть. Во всех примерах, которые я видел просто писалось $mysqli->query(...). Строк подключения там не было, словно оно уже как таковое имеется.
Я попытался вникнуть в систему "постоянных подключений", но так и не разобрался, что к чему. К тому же там ограничения на кол-во одновременных соединений есть.
Очень прошу помочь с этим вопросом. Из-за него буквально стоит весь проект.


Ответ

Нашел ответ.
На странице, на которой будет производиться живой поиск, необходимо создать постоянное соединение с помощью mysqli:
/* Пермаментное подключение к БД */ $pMysqli = new mysqli('p:'.DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);
Для того, чтобы подключение было постоянным, необходимо добавить префикс "p:". Об этом я знал.
После этого, в начале php скрипта, к которому обращается ajax, необходимо написать ту же строчку. Если соединение уже существует, то никакого подключения не состоится, зато у вас уже будет объект соединения.
Пример:
Страница, на которой есть форма живого поиска - somepage.php

Обработчик Ajax запроса - handler.php
$data = $pMysqli->query("SELECT Content FROM TestTable ORDER BY Content LIMIT 1");
/* Работа с полученными данными */ ?>

В чем разница между шаблонами, паттернами и дженериками?

В чем разница между шаблонами, паттернами и дженериками? Являются ли все три понятия одинаковыми по смыслу и разница в переводе? Или разница заключается в том как реализуются в разных языках одинаковый по смыслу функционал типа List?
В частности вопрос возник во время прочтения сравнений языков программирования и частого тезиса "В C++ есть шаблоны и нигде больше таких нет"


Ответ

Шаблоны (templates) в Си++ это частный случай обобщённых типов (generic types). Обобщённые типы в Си++ очень мощные, Тьюринг-полные. Вы, например, можете вычислять числа Фибоначчи во время компиляции с помощью шаблонов Си++.
В других языках (Java, C#) обобщённые типы гораздо проще. Соответственно, проще и компилятор, и отлов странных труднопонимаемых ошибок (см. Александреску головного мозга).
Обобщённые типы — довольно старая концепция, придуманная в одной из первых реализаций ML. Она позволяет избежать дублирования кода, не зависящего от конкретного типа, либо накладывающего на тип не очень строгие ограничения.
Например, обобщённый алгоритм, считающий среднее арифметическое коллекции объектов, накладывает на тип элементов два ограничения: элемент можно сложить с элементом и элемент можно разделить на целое число (такой тип ограничений реализован далеко не во всех языках программирования).
Обобщённая структура данных "список" не накладывает на тип элементов никаких ограничений, кроме тех, которые и так присущи любым объектам. В старых версиях таких языков, как C++, Java, C# без поддержки обобщённых типов, приходилось писать отдельную реализацию списка для каждой иерархии, либо постоянно приводить типы вверх и вниз
Что касается паттернов (patterns) то обычно под ними понимают крупные единицы проектирования объектно-ориентированных программ. Например, такие решения доступа к базам данных, как repository, unit of work, active record являются паттернами (они, описаны, в частности, в книгах Фаулера). DDD описывает паттерны aggregate root и value-object, Dependency Injection реализуется с помощью паттернов composite root, constructor injection и т.д.
Есть так же главная книга по паттернам, которая называется — Паттерны объектно-ориентированного проектирования.

Jenkins. Как сделать чтобы каждый второй билд не запускал тесты?

Что нужно поменять/установить в настройках джоба(item) Jenkins, чтобы каждый второй билд не запускал тесты?


Ответ

Вариант 1
Можно поставить Conditional BuildStep Plugin - он позволяет задавать условие для выполнения отдельного шага сборки. В вашем случае таким условием является четность номера сборки.
По порядку:
Добавляете шаг Conditional step (single) в билд В качестве условия Run? выбираете Boolean condition В качестве Token задаете выражение:
${GROOVY,script = "(Thread.currentThread().executable.number) %2 == 0"} В качестве Builder указываете Invoke Maven 3 и настраиваете ваш обычный maven-билд. Повторяете шаги 1-4, но задаете условие для нечетности:
${GROOVY,script = "(Thread.currentThread().executable.number) %2 != 0"}
и запускаете maven-билд с флагом -DskipTests=true
PS. У вас так же должны быть установлены Groovy Plugin и Token Macro Plugin, в настройках Jenkins должен быть включен флаг Groovy -> Allow token macro processing

Слышал есть более простой способ, а именно, использовать переменную среды Jenkins - BUILD_NUMBER.
По сути мы и так использовали BUILD_NUMBER, только не через переменные среды, а через API.
Если хотите без обойтись без groovy в голову приходят два варианта:
Вариант 2. Можно взять EnvInject Plugin и перед сборкой инжектить в переменную, скажем $RUN_TESTS, значение $(($BUILD_NUMBER % 2)), что будет давать нам либо 1 либо 0. А в переменную $DONT_RUN_TESTS соответственно противоположное значение: $((1 - $BUILD_NUMBER % 2))
Но это не избавит нас от Conditional BuildStep Plugin. Просто Token-ы поменяются на ${ENV,var='RUN_TESTS'} и ${ENV,var='DONT_RUN_TESTS'}
Conditional BuildStep Plugin вообще всеядный и в качестве true рассматривает значения 1, y, yes, t, true, on, run Вариант 3. Другой вариант - настроить в самом pom.xml файле проекта средствами maven-а профиль в котором будут глушиться тесты. Пусть он называется no-tests. Теперь все тем же EnvInject-ом заинжектим переменную окружения, например $MVN_PROFILE, которая для четных билдов пустая, а для нечетных - содержит значение -P no-tests, то есть $MVN_PROFILE должна содержат результат вычисления:
$(if [[ $(($BUILD_NUMBER % 2)) -eq 0 ]]; then echo '-P no-tests'; fi )

Правильный разбор строки на c#

Например есть массив стоп слов
var stops = new string[] { "район","р-н","город","г.","посёлок городского типа","п.г.т.","р.п.","рабочий посёлок","к.п.","курортный посёлок","к.","кишлак","пс","поселковый совет","сс","сельсовет", "смн","сомон","вл.","волость","д.п.","дачный поселковый совет","п.","посёлок сельского типа","н.п.","населённый пункт","п.ст.","посёлок при станции","ж/д ст.", "железнодорожная станция","с.","село","м.","местечко","д.","деревня","сл.","слобода","ст.","станция","ст-ца","станица","х.","хутор","у.","улус","рзд.","разъезд","клх", "колхоз","свх","совхоз","зим.","зимовье" };
От сервиса прилетает разный набор в строке, например может прилететь "деревня Новгородская" или "Нижний Новгород" Как правильно реализовать чистку входящей строки от стоп слов? Короче, если кратко, то в строке должно остаться только название населенного пункта.


Ответ

public static string Sanitize(string s) { var stops = new string[] { "район","р-н","город","г.","посёлок городского типа","п.г.т.","р.п.","рабочий посёлок","к.п.","курортный посёлок","к.","кишлак","пс","поселковый совет","сс","сельсовет", "смн","сомон","вл.","волость","д.п.","дачный поселковый совет","п.","посёлок сельского типа","н.п.","населённый пункт","п.ст.","посёлок при станции","ж/д ст.", "железнодорожная станция","с.","село","м.","местечко","д.","деревня","сл.","слобода","ст.","станция","ст-ца","станица","х.","хутор","у.","улус","рзд.","разъезд","клх", "колхоз","свх","совхоз","зим.","зимовье" };
stops = stops.OrderByDescending(st => st.Length).ToArray();
foreach (string stop in stops) { // не создавать каждый раз, кэшировать в статике! Regex r = new Regex(@"(\s|^)" + Regex.Escape(stop) + @"(\s|$)"); s = r.Replace(s, ""); }
return s; }
public static void Main(string[] args) { Console.WriteLine(Sanitize("деревня Новгородская")); Console.WriteLine(Sanitize("посёлок городского типа Новгородский")); }
Fiddle: https://dotnetfiddle.net/88YJ7X

Проверка существования календарного дня

У меня есть 3 числа int: year, month, day, которые должны соответствовать дню календаря.
Можно ли с помощью каких-либо стандартных библиотек проверить, что такой календарный день существует?


Ответ

public static boolean isDateValid(int year, int month, int day) { boolean dateIsValid = true; try { LocalDate.of(year, month, day); } catch (DateTimeException e) { dateIsValid = false; } return dateIsValid; }

Не могу найти объяснение работы sql запросов

Есть некоторые таблицы в oracle.
Так вот собственно попрос: почему иногда конструкция типа
select * from TABLE t where to_char(t.field) = 'somevalue'
работает лучше(т.е. быстрее отрабатывает, план запроса лучше, меньше стоимость запроса) чем
select * from TABLE t where t.field = 'somevalue'
Данное поле проиндексировано. То самое с to_date. Такое чувство что индекс по неведомым причинам не подхватывается при "прямых" запросах. Особенно такое проявляется в сложных запросах, где объединяется несколько таблиц.
Версия oracle: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0
Количество данных при выборе не меняется.
План ДО использования to_date на TABLE2
select * from TABLE1, TABLE2, TABLE3 where TABLE1.id = TABLE2.TABLEID and TABLE1.id = TABLE3.TABLEID and TABLE3.DATAFIELD + 1 > trunc(sysdate) and TABLE1.DATAFIELD + 1 > trunc(sysdate) and ((TABLE2.DATAFIELD = trunc(sysdate)) or (TABLE1.ID = nvl(0, 0)))
------------------------------------------------------------- Plan hash value: 2464832983 ------------------------------------------------------------- | Id | Operation | Name | ------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | CONCATENATION | | | 2 | NESTED LOOPS | | | 3 | NESTED LOOPS | | | 4 | NESTED LOOPS | | | 5 | TABLE ACCESS BY INDEX ROWID| TABLE1$ | | 6 | INDEX UNIQUE SCAN | PK_TABLE1$ | | 7 | TABLE ACCESS BY INDEX ROWID| TABLE2$ | | 8 | INDEX RANGE SCAN | TABLE2$TABLEID | | 9 | INDEX RANGE SCAN | TABLE3$TABLEID | | 10 | TABLE ACCESS BY INDEX ROWID | TABLE3$ | | 11 | HASH JOIN | | | 12 | TABLE ACCESS FULL | TABLE2$ | | 13 | NESTED LOOPS | | | 14 | NESTED LOOPS | | PLAN_TABLE_OUTPUT ------------------------------------------------------------- | 15 | TABLE ACCESS FULL | TABLE3$ | | 16 | INDEX UNIQUE SCAN | PK_TABLE1$ | | 17 | TABLE ACCESS BY INDEX ROWID | TABLE1$ | -------------------------------------------------------------
План ПОСЛЕ использования to_date на TABLE2
select * from TABLE1, TABLE2, TABLE3 where TABLE1.id = TABLE2.TABLEID and TABLE1.id = TABLE3.TABLEID and TABLE3.DATAFIELD + 1 > trunc(sysdate) and TABLE1.DATAFIELD + 1 > trunc(sysdate) and ((to_date(TABLE2.DATAFIELD) = trunc(sysdate)) or (TABLE1.ID = nvl(0, 0)))
------------------------------------------------------------- Plan hash value: 1081346625 ------------------------------------------------------------- | Id | Operation | Name | ------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | CONCATENATION | | | 2 | NESTED LOOPS | | | 3 | NESTED LOOPS | | | 4 | NESTED LOOPS | | | 5 | TABLE ACCESS BY INDEX ROWID| TABLE1$ | | 6 | INDEX UNIQUE SCAN | PK_TABLE1$ | | 7 | TABLE ACCESS BY INDEX ROWID| TABLE2$ | | 8 | INDEX RANGE SCAN | TABLE2$TABLEID | | 9 | INDEX RANGE SCAN | TABLE3$TABLEID | | 10 | TABLE ACCESS BY INDEX ROWID | TABLE3$ | | 11 | NESTED LOOPS | | | 12 | NESTED LOOPS | | | 13 | NESTED LOOPS | | | 14 | TABLE ACCESS FULL | TABLE2$ | PLAN_TABLE_OUTPUT ------------------------------------------------------------- | 15 | TABLE ACCESS BY INDEX ROWID| TABLE1$ | | 16 | INDEX UNIQUE SCAN | PK_TABLE1$ | | 17 | INDEX RANGE SCAN | TABLE3$TABLEID | | 18 | TABLE ACCESS BY INDEX ROWID | TABLE3$ | -------------------------------------------------------------


Ответ

В таких случаях важно рассматривать весь запрос в целом, а не его отдельные элементы. Потому как изменение предпочтений оптимизатора по одной таблице может приводить к кардинальному изменению его подхода к другим таблицам в этом же запросе.
В данном, конкретном, случае индекс по полю даты был вообще не причем. Oracle и не пытался его использовать. Применение функции to_date к полю приводило к тому, что оптимизатор, скорее всего, не использовал статистику по данному полю и предполагал наличие большого количества записей в таблице по заданному условию. Что, в свою очередь, заставляло оптимизатор выбирать более разумный план подклейки других двух таблиц и идти по тем, другим таблицам по индексу.
А в варианте без to_date оптимизатор использовал статистику по полю даты, считал, что по конкретной дате он выберет мало данных. А для малого количества данных выбираемых на первом шаге он считал более оптимальным выполнить полное сканирование, без использования индексов по второй таблице, что приводило к росту времени выполнения, т.к. данных оказывалось больше, чем предполагал оптимизатор.
P.S. Из за наличия OR в полном запросе оптимизатор шел по пути выполнения двух разных запросов для первой части OR и для второй (которая и была не оптимальной). Ситуация была исправлена заменой условия OR таким образом, что бы в нем участвовали только поля одной таблицы.

Как перевести `VB.NET` код c лямбда-выражениями в код с циклами

Проект под .NET 3.5 в Visual Studio 2008, это продолжение этого вопроса про сериализацию/десериализацию и динамически меняющиеся свойства JSON.
В этом ответе имеется решение вопроса несовместимости форматов сериализаторов, которое состоит в том что по умолчанию Newtonsoft.Json сохраняет публичные свойства в JSON, а DataContractJsonSerializer сохраняет приватные свойства. Соответственно сериализация одного и того же объекта дает разный результат.
Для DataContractJsonSerializer
{ "ExProperty": { "_disabled": false, "_el_class": null, "_enum_values": [], "_id": "124", "_inline_script": null, "_inline_style": null, "_innerHTML": null, "_input_max": 0, "_input_min": 0, "_input_min_zero": false, "_input_subtype": null, "_nolabel": true, "_onclick": null, "_order": 0, "_parent_wrapp_class": "rrrrrrr", "_placeholder": null, "_value": null, "_width": 0, "_wrapp_class": null, "_wrapp_col_md": 55, "_wrapp_label_class": "eeee", "_dt_append": null, "_dt_append_name": null, "_dt_name": null, "_fieldSet": [ "qqqqqqqqqqqqq", "aaaaaaaaaaa", "ssssssssssssss", "dddddddddddddd", "fgfffffffffffffffffff" ], "_fieldset_name": "aaaaaaaaaaa", "_isfiltr": false, "_lbl": null, "_lbl_short": null, "_lkp_filter": null, "_lkp_idas": null, "_lkp_nameas": null, "_lkp_table": null, "_req": false, "_sh_in_add": false, "_sh_in_edit": false, "_sh_in_list": false, "_type": null }, "PropertyOne": "значение 1", "PropertyThree": null, "PropertyTwo": "значение 2" }
Для Newtonsoft.Json
{ "PropertyOne": "значение 1", "PropertyTwo": "значение 2", "PropertyThree": null, "ExProperty": { "fieldSets": [ "qqqqqqqqqqqqq", "aaaaaaaaaaa", "ssssssssssssss", "dddddddddddddd", "fgfffffffffffffffffff" ], "fieldset_name": "aaaaaaaaaaa", "lbl": null, "lbl_short": null, "type": 0, "req": false, "lkp_table": null, "lkp_nameas": null, "lkp_idas": null, "lkp_filter": null, "dt_name": null, "dt_append_name": null, "dt_append": null, "sh_in_edit": false, "sh_in_add": false, "sh_in_list": false, "isfiltr": false, "order": 0, "wrapp_col_md": 55, "parent_wrapp_class": "rrrrrrr", "wrapp_class": null, "wrapp_label_class": "eeee", "el_class": null, "value": null, "innerHTML": null, "placeholder": null, "nolabel": true, "width": 0, "onClick": null, "inlineStyle": null, "Disabled": false, "Id": "124", "inlineScript": null, "inputSubtype": null, "InputMinZero": false, "inputMin": 0, "inputMax": 0, "EnumValues": [] } }
Требуется переписать класс из ответа, так чтобы он компилировался в 2008 студии.
Imports System.Reflection Imports Newtonsoft.Json Imports Newtonsoft.Json.Serialization
Public Class MyContractResolver Inherits DefaultContractResolver Protected Overrides Function CreateProperties(type As Type, memberSerialization As MemberSerialization) As IList(Of JsonProperty) Dim props = type.GetProperties(BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance). Select(Function(p) MyBase.CreateProperty(p, memberSerialization)). Union(type.GetFields(BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance). Select(Function(f) MyBase.CreateProperty(f, memberSerialization))).ToList()
props.ForEach(Sub(p) p.Writable = True p.Readable = True End Sub) Return props End Function End Class
Сейчас код не воспринимается, ибо нет таких конструкций в 2008 версии.


Ответ

Попробуйте такой вариант, должно сработать:
Imports System.Reflection Imports Newtonsoft.Json Imports Newtonsoft.Json.Serialization
Public Class MyContractResolver Inherits DefaultContractResolver Protected Overrides Function CreateProperties(ByVal type As Type, ByVal memberSerialization As MemberSerialization) As IList(Of JsonProperty) Dim props As New List(Of JsonProperty)()
Dim propsInfo As PropertyInfo() = type.GetProperties(BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance)
For Each pi As PropertyInfo In propsInfo Dim jp = MyBase.CreateProperty(pi, memberSerialization) If Not props.Contains(jp) Then props.Add(jp) End If Next
Dim fieldsInfo As FieldInfo() = type.GetFields(BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance)
For Each pi As FieldInfo In fieldsInfo Dim jp = MyBase.CreateProperty(pi, memberSerialization) If Not props.Contains(jp) Then props.Add(jp) End If Next
For Each p As JsonProperty In props p.Writable = True p.Readable = True Next
Return props End Function End Class

Задача на отрезки на числовой прямой

Записался на курс алгоритмы и структуры данных. Не могу никак решить задачу: На числовой прямой окрасили N отрезков. Известны координаты левого и правого концов каждого отрезка (Li и Ri). Найти сумму длин частей числовой прямой, окрашенных ровно в один слой. Используемый язык java, другие также принимаются
input
3
1 4 7 8 2 5
output 3 input
9
2 9 0 1 7 12 5 12 9 13 9 14 10 18 17 18 2 10
output 4
UPD Что я пытался делать 1) сортировать все точки и держать к какому концу отрезка она находиться на 1 первый тест легко пишутся условия когда нужно посчитать сумму ко 2му не подходит
int sum = 0; if(mass.length==1) sum+=mass[1].dot-mass[0].dot; else { sum+= mass[1].dot-mass[0].dot; for (int i = 2; i < n * 2; i++) { if(mass[i].l==false){ // если это не левый конец if (mass[i-1].l==false) sum+=mass[i].dot-mass[i-1].dot; if(mass[i-1].l==true&&mass[i-2].l==false) sum+=mass[i].dot-mass[i-1].dot; }else {
if(mass[i-1].l==true) sum+= mass[i].dot-mass[i-1].dot;
}
2) Сортировать все отрезки в виде классов (point( 1 4) point (2 5) point (7 8)) также с ифами все возможные варианты не получилось покрыть, Есть какие-то еще идеи или только в этих 2-х направлениях нужно искать подходящие условия срабатывания счетчика
UPD
Вот похожая задача на нахождение длины объединения отрезков на прямой. ток не совсем понимаю синтаксис и как перевести на java
unsigned segments_union_measure (const vector > & a) { unsigned n = a.size(); vector > x (n*2); for (unsigned i=0; i sort (x.begin(), x.end());
unsigned result = 0; unsigned c = 0; for (unsigned i=0; i

Ответ

Задачи на интервалы решаются сортировкой координат, и перебором подряд от меньших к большим, считая «текущее» кол-во активных.
Напр., даны отрезки [1,5], [2,3], [3,9]
Тут ещё важно, каковы крайние точки - для простоты считаем, что все края «включены».
Сортируем координаты, не забывая, где какая - одни из них точки входа (in), другие - выхода (out):
1 i 2 i 3 o 3 i 5 o 9 o
Изначально кол-во включённых слоёв 0. Когда "i" добавляем 1, когда "o" – вычитаем. Пошли:
- - 0 1 i 1 - начался нужный отрезок - в результат добавим [1, ? 2 i 2 - != 1, закончился – в результат добавили [1,2] 3 o 1 - снова начался нужный 3 i 2 - и тут же закончился, ничего не делаем 5 o 1 - начался нужный [5, ? 9 o 0 - закончился, в результат добавили [5,9]
Результат: [1,2], [5,9]. Складываем длины 1+4 = 5. Ответ: 5

Фильтрация по характеристикам товара

Есть таблица с характеристиками товаров и столбцами Good_ID, Field_ID, Value. Может быть сколько угодно записей с одним Good_ID и разными Field_ID и Value
Field_ID - это идентификатор определенной характеристики
Нужно написать запрос, чтобы выбирались Good_ID, которые удовлетворяют нескольким парам Field_ID и Value. По сути фильтрация по характеристикам товара.
Не могу придумать, как одним запросом выбрать из таблицы все товары, у которых цвет синий и вес до 1кг.
Обновление
Всем спасибо. В общем в итоге получилось реализовать вот так
SELECT DISTINCT Good_ID FROM chars WHERE Message_ID IN (SELECT Good_ID FROM chars WHERE Field_ID = 3 AND Value = 'серый') AND Message_ID IN (SELECT Good_ID FROM chars WHERE Field_ID = 2 AND Value = '3')
Если я не правильно составил запрос - поправьте плз.


Ответ

У Вас должна быть таблица со списком товаров. Типа goods. Т.е. Good_ID это id из этой таблицы. Далее, предположим, что:
Ваша таблица с характеристиками называется attributes Field_ID для цвета = 1 Field_ID для веса = 2
Тогда нужный Вам запрос будет выглядеть так:
SELECT g.* FROM goods g JOIN attributes aCo AS g.id=aCO.Good_ID AND aCo.Field_ID=1 AND aCo.value='синий' JOIN attributes aW AS g.id=aW.Good_ID AND aW.Field_ID=2 AND aW.value=1
Этот запрос покажет Вам все товары из таблицы goods, у которых цвет (Field_ID=1) синий, а вес (Field_ID=2) = 1.

У меня на сайтах реализована описанная Вами схема, поэтому позволю себе дать Вам совет: будет лучше, если Вы сделаете сводную таблицу всех товаров и их аттрибутов. Можно туда добавить другую информацию: цены, описания, названия, картинки...
Что-то типа такого:
Good_ID SKU title price a1 a2 a3 ------- --------- --------------------- ------ --- --- --- 2 [артикул] [наименование товара] 450.00 red 3 45 452 [артикул2] [наименование товара 2] 15.00 white 5 64
a1, a2, a3 - это значения аттрибутов 1, 2 и 3 (у Вас Field_ID). В зависимости от того, как часто меняется информация о товаре можно такую таблицу генерировать заново раз в час / несколько часов / раз в сутки.
Имея такую таблицу, Вам будет намного проще доставать данные из базы, делать отчеты, можно сделать быстрый (очень быстрый) поиск на сайте (ведь запросы любой сложности будут всегда в одну таблицу)... ну еще много всего....
Очень советую.

Как заменить префикс 'test_' на 'should_' в модульных тестах с примением unittest?

При использовании библиотеки unittest, которая входит в стандартную python библиотеку программист свои тестовые методы вынужден сопровождать test_. Мне хочется уточнить, это обязательное требование или же все-таки есть способ заменить его другим, к примеру should_?


Ответ

Во всех примерах кода ниже буду считать, что доступен класс с тестами:
class MyTests(unittest.TestCase): def test_simple(self): self.assertTrue(True)
def test_complicated(self): self.assertTrue(False)
def should_pass(self): self.assertTrue(True)
def should_fail(self): self.assertTrue(False)
Использование поля testMethodPrefix в TestLoader
Нашёл способ с использованием ручного запуска через TestLoader
import unittest
def run_tests(): loader = unittest.TestLoader() loader.testMethodPrefix = 'should' # задаём требуемый префикс тестов suite = loader.loadTestsFromTestCase(MyTests) unittest.TextTestRunner().run(suite)
if __name__ == '__main__': run_tests()
TestLoader имеет поле testMethodPrefix, в которое можно записать требуемый префикс тестов. В этом случае будут запущены только методы, которые начинаются с указанной строки.

Создание собственного TestLoader, использующего регулярные выражения для поиска тестов в классе
Как вариант, можно перегрузить класс TestLoader и сделать так, чтобы он искал не просто по совпадению префикса, а по регулярному выражению (использовал camelCase для соответствия стилю именования, принятому в unittest):
import unittest import functools import re
class MyTestLoader(unittest.TestLoader): def getTestCaseNames(self, testCaseClass): """Return a sorted sequence of method names found within testCaseClass """ def isTestMethod(attrname, testCaseClass=testCaseClass, pattern=self.testMethodPrefix): return (re.match(pattern, attrname) and callable(getattr(testCaseClass, attrname))) testFnNames = list(filter(isTestMethod, dir(testCaseClass))) if self.sortTestMethodsUsing: testFnNames.sort(key=functools.cmp_to_key(self.sortTestMethodsUsing)) return testFnNames
def run_tests(): loader = MyTestLoader() loader.testMethodPrefix = 'should|test' suite = loader.loadTestsFromTestCase(MyTests) unittest.TextTestRunner().run(suite)
if __name__ == '__main__': run_tests()
Такой загрузчик тестов запустит и стандартные тесты, и тесты, начинающиеся с should

Использование протокола load_tests
Ещё один способ -- это создать функцию load_tests, которая возвращает TestSuit для модуля. Если в модуле определена такая функция, то библиотека попробует вызвать её для получения списка тестов:
def load_tests(loader, tests, pattern): loader.testMethodPrefix = 'should' return loader.loadTestsFromTestCase(MyTests)

Источники:
Документация по библиотеке unittest Документация по TestLoader Протокол load_tests

Ключевое слово class перед класс-мембером

Считается ли ключевое слово class перед класс-мембером как своего рода forward declaration класса, чтобы компилятор не беспокоился, что за "идентификатор".

Идентичны ли эти фрагменты кода?
class Foo { private: class Bar* a; };
и
class Bar; class Foo { private: Bar* a; };


Ответ

Да, идентичны.
Согласно 3.3.2 Point of declaration [basic.scope.pdecl], для таких объявлений, которые называются elaborated-type-specifier, имя объявляется во внешней области видимости.
Это можно продемонстрировать таким кодом:
struct Foo { struct Bar* a; };
struct Bar {};
int main() { Bar b; Foo f; f.a = &b; }
Однако для объявлений вида class name;, имя объявляется в той же области видимости, например
struct Foo { struct Bar; };
struct Foo::Bar {};

Как сделать кросс-доменный AJAX POST запрос?

Есть форма с инпутами. При клике на кнопку "Отправить", браузер делает пост запрос на указанный адрес и пользователь попадает на новую страницу. Это стандартный алгоритм работы


Задача заключается в том, чтобы заменить это дело на AJAX. Чтобы пользователь ввёл данные, нажал на кнопку и увидел сообщение об успешной отправке, но сам не перенаправлялся на другую страницу.
Проблема в том, что домен, на который делается POST запрос отличается от того, с которого идёт запрос.
Прочитал о том, что это можно сделать с помощью CORS. Но, как я понял, там сервер должен вернуть результат о том, разрешает ли он такой запрос или нет.
А существует ли метод решения поставленной задачи, который бы не спрашивал разрешения у сервера?
Существует ли метод фонового POST запроса на другой домен --- такой, чтобы ничего не настраивать дополнительно на сервере?
Буду признателен, если кто-нибудь приведёт пример.
UPDATE
Я изменил dataType на jsonp, но, как мне подсказали, получается GET, а не POST запрос.


Ответ

Можно создать скрытую форму, у которой target указывает на скрытый же iframe, заполнить ее из скрипта и отправить. Ограничение - ответ от сервера таким образом не получить.

Два параметра в лямбда-выражении

Как лямбда-выражению передать два разных параметра? Например
Function getConcatenatedString = (amount, s) -> {...}
amount - Integer, s - String.
Есть ли еще какая-то возможность, кроме как определения интерфейса вроде:
@FunctionalInterface interface Function3 { public R apply (A a, B b); }


Ответ

Вероятно, Вам нужна следующая конструкция:
BiFunction getConcatenatedString = (Integer amount, String s) -> { return Integer.toString(amount) + " " + s; };
Кстати, поскольку выражение в лямбде единственно, её можно записать покороче:
BiFunction getConcatenatedString = (Integer amount, String s) -> Integer.toString(amount) + " " + s;

Как реализовать шифрование данных на PHP

Вот пример на JS:
function decryptRandomNumber (pwdHash, encryptedRandomNumber) { var key = CryptoJS.enc.Utf8.parse(pwdHash);
var encrypted = CryptoJS.enc.Hex.parse(encryptedRandomNumber.toUpperCase());
var result = CryptoJS.AES.decrypt({ ciphertext: encrypted }, key , { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8);
return result; }
function encryptPwdHash (pwdHash, randomNumber) {
var randomNumberMd5 = CryptoJS.MD5(randomNumber).toString().toUpperCase(); var key = CryptoJS.enc.Utf8.parse(randomNumberMd5); var result = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(pwdHash), key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).ciphertext;
return result; } // пример на js - шифрование var password = '123456'; var pwdHash = CryptoJS.MD5(password).toString().toUpperCase(); var encriptResult = encryptPwdHash (pwdHash, '3456'); //
Скриншот результата если привести в строку то f46492dc512a6df5cd7c6b9ee50e7cc44fb2337c1605726518d353ce800d5cc05d4d5540dd7674850079e785ab5f3b77
Нужно переписать на PHP.
Расшифровку смог сделать вот этой функцией
function aes128_cbc_decrypt($key, $data, $iv) { $data = pack("H*", $data); $iv = pack("H*", $iv); $dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv); return $dec; }
Входящие параметры --> $key = strtoupper(md5($password)); хеш пароля $data = '54BAA6158E81E1069EA2AB1C4F9D1F29';- хеш рандомного числа $iv = '00000000000000000000000000000000'; - вектор в виде 16 - ти ричной константы.
Вот теперь нужно зашифровать обратно пароль с помощью случайного числа и отправить. Написал функцию которая делает подобное:
function aes128_cbc_encript($key, $data, $iv) { $key = pack("H*", strtoupper(md5($key))); //var_dump($data); //$data = pack("H*", $data); $iv = pack("H*", $iv); //$enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv); $enc = openssl_encrypt($data, 'AES-128-CBC', $key, true, $iv); return bin2hex($enc); }
Пробую запускать
$decript = '34345'; // расшифрованное рандомное число $pswdHash = strtoupper(md5($password));
$encript = aes128_cbc_encript($decript, $pswdHash, '00000000000000000000000000000000');
На выходе получаю нечто - 72fc1b49db86787b749c3323421496af00933eb79a9b7d845a51f5ea3fefdf750800554f5fdf0c7d3d765fe7f6653da3
Такой шифр и должен быть по длинне и в 16 - ти разрядном виде, но он не правильный и при отправке на сервер он не расшифровуется.
Вот пример функции на Oracle, которая на сервере делает расшифровку
Fc_Decrypt_Password_Hash(In_Encrypted_Password_Hash In Varchar2, In_Random_Number_Md5 In Varchar2) Return Varchar2 Is Raw_Random_Number_Md5 Raw(2000); Raw_Result Raw(2000); Result Varchar2(2000); Begin Raw_Random_Number_Md5 := Utl_I18n.String_To_Raw(Upper(In_Random_Number_Md5), 'AL32UTF8'); Raw_Result := Dbms_Crypto.Decrypt(Typ => Dbms_Crypto.Aes_Cbc_Pkcs5, Src => Upper(In_Encrypted_Password_Hash), Key => Raw_Random_Number_Md5); Result := Utl_I18n.Raw_To_Char(Raw_Result, 'AL32UTF8'); Return(Result); End;


Ответ

Во-первых, если вы действительно хотите защитить обмен сообщениями - пользуйтесь готовыми решениями.
Функция openssl_encrypt не использует весь $key, а только первые 16 байт, остальные отбрасываются (для AES-128). Хотя это только практический опыт, возможно это верно не для всех версий. В качестве $key у вас используется хэш md5 в 16-ричном формате, а это 32 байта. CryptoJS, использует весь ключ (или по крайней мере больше 16 байт).
Ожидать, что результаты шифрований совпадут, не приходится.
Функция mcrypt_encrypt не умеет Pkcs7. Она всегда выравнивает блок нулями (и это небезопасно). Хоть в вашем случае выравнивание и не требуется (длина исходного текста всегда делится на 16), по вышеуказанному стандарту все равно нужно добавить выравнивание, это будут 16 байт 0x10
Пример рабочего кода (практически повторяет ваш пример на js):
function encrypt(){ $data=strtoupper(md5('123456')); $data.=str_repeat(chr(16), 16);// добавляем выравнивание $key=strtoupper(md5('3456')); $iv=hex2bin(str_repeat('00', 16)); $enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv); return bin2hex($enc); } var_dump(encrypt()); // -> string(96) "f46492dc512a6df5cd7c6b9ee50e7cc44fb2337c1605726518d353ce800d5cc05d4d5540dd7674850079e785ab5f3b77"

Семантика объявлений 2D-массивов в Си

Не могу понять семантику следующего выражение на Си:
char (*daytab)[13]
Оно эквивалентно такому выражению:
char daytab[2][13]
В первом выражении сообщается, что так объявленный параметр функции - указатель на массив из 13 элементов. Наличие круглых скобок здесь обязательно, потому что квадратные скобки [] имеют больший приоритет, чем знак ссылки *. Без скобок это было бы объявление массива из 13 указателей на данные типа char:
char daytab[13]
Объясните, что происходит в первом определении? Подобные конструкции под капотом, как правило, выглядят очень просто: как работа с каким-нибудь регистром EDI, а понять семантику таких выражений бывает нелегко.
Если разбирать первый пример по частям справа налево, то можно попытаться объяснить это так:
объявляется массив из 13 элементов Слева находится тип данных, хранящихся в массиве типа данных char (*daytab) не поддается человеческой интерпретации, и здесь я застопорился
Помогите разобраться


Ответ

В с/с++ не разбирают справа-налево. А разбирают по спирали. Вот есть чудесный сервис - http://www.cdecl.org/ , который помогает парсить подобые вещи.

Какое отличие между параметрами compileSdkVersion и targetSdkVersion?

Какое отличие между параметрами compileSdkVersion и targetSdkVersion?


Ответ

Немного дополню исходный ответ (по ссылке из комментария @dubok79) + попытаюсь объяснить на пальцах.
compileSdkVersion - та версия SDK, с которой будут собираться билды. По большому счету, влияет на всевозможные сообщения отладки. В финальный билд само SDK, конечно же, никак не "зашивается", более того, даже упоминания об этой настройке в нем не будет.
Лично я стараюсь держать ее равной targetSdkVersion. В теории возможна, например, следующая ситуация (чисто выдуманная, но логика должна быть понятна). С новой версией SDK несколько методов стали deprecated. Если повысить значение параметра, будем получать предупреждения при сборке проекта. Однако в данный момент команде надо срочно делать новый функционал, избавлением от устаревшего получится заняться только по завершении. Тогда лучше не повышать, чтобы среди игнорируемых пока предупреждений не пропустить важные.
targetSdkVersion - максимальная версия, под которую вы проверяли свое приложение. Это нужно Android, чтобы понимать - можно ли использовать свежий функционал в приложении или оно может оказаться к нему не готово. Помогает избегать ситуаций, когда с обновлением версии оси поменялись какие-то значения / поведения по-умолчанию, от чего ваше приложение может начать работать хуже. Пример, приходящий в голову: когда обязательность кнопки меню убрали и заменили на ActionBar.
Опять же, в моем случае стараюсь держать этот параметр всегда актуальным последней версии оси. Но переход - это всегда необходимость проверить, не сломалось ли чего, комплексно пробежать по приложению. Потому не всегда он делается сразу и быстро.

Подключение к удаленной бд MySQL в Android

Необходимо подключиться к внешней БД MySQL в Android приложении, которое бы использовало ресурсы готового сервиса, но без API. Знаю, что это нехорошо, но просто стоит такая задача.
Как это можно сделать?


Ответ

Для того что бы подключится к БД Вам потребуется:
1.Подключить к проекту JDBC Driver для MySQL. Если пользуетесь AS то в зависимостях укажите следующую строку:
compile 'mysql:mysql-connector-java:5.1.6'
2.Перед первым обращением к базе необходимо зарегистрировать драйвер:
try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { System.out.println("Where is your MySQL JDBC Driver?"); e.printStackTrace(); return; }
Строка com.mysql.jdbc.Driver зависит от подключенного драйвера.
3.Получаем соединение с базой так:
Connection conn = DriverManager.getConnection("jdbc:mysql://hostname:port/dbname","username", "password");
Естественно заменяем hostname, port, dbname, username и password на свои.
PS: и да, не забываем производить соединение и всяческие манипуляции с базой не в UI потоке. Про разрешения в манифесте так же забывать не стоит.

Почему не работает псевдоселектор first-child?

Есть базовая HTML структура с двумя параграфами в Body. Почему, когда я пробовал обратиться к первому параграфу через псевдо селектор p:first-child, ничего не вышло, но сработало p:nth-child(2). Ведь это первый параграф в родителе Body, почему так?

Paragraph-1

Paragraph-2



Ответ

обернул твой код в

и все заработало

Paragraph-1

Paragraph-2


Убрать ActionBar (Toolbar?)

Здравствуйте.
Появилась небольшая проблема:

Пустое пространство под ActionBar - на Android 4 оно не отображается, только на 5+.
Фрагмент из манифеста:

Styles.xml:








В лаяуте про actionbar ничего нет


Ответ

Поставьте в манифест тему android:theme="@style/AppTheme.NoActionBar" или перенесите те две строчки из NoActionBar в AppTheme

Организация процесса код ревью для небольшой команды с помощью Upsource

У JetBrains есть клевая система код ревью Upsource
В моей команде 3 человека. Хочу включить в наш рабочий процесс прохождение код ревью как обязательное требования вливания кода в ветку девелоп.
Задача: все строчки кода вливаемые в ветку девелоп обязаны успешно пройти код ревью.
Я хочу узнать у тех кто использует Upsource как и когда вы создаете код ревью. Его создает тот кто написал код? Как вы следите что изменения прошли код ревью? Какие соглашения с командой вы выработали по теме код ревью?
Пожалуйста, опишите ваш рабочий процесс с этой системой.


Ответ

С Upsource я не работал, могу описать процесс на примере Atlassian Stash (недавно переименован в Bitbucker Server). Судя по тому, что я быстренько прочитал об Upsource, там есть аналогичная функциональность. Все описанное справедливо для использования git flow/github flow (судя по вашим предыдущим вопросам вы используете гит).

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

Общие соображения на эту тему такие:
у разработчиков не должно быть возможности влить свой код в условный мастер напрямую код вливается после соблюдения нескольких условий: зеленый билд, пройденное код-ревью, отсутствуют конфликты с мастером

Теперь конкретные ответы на вопросы.
Его создает тот кто написал код?
Да.
Как вы следите что изменения прошли код ревью?
Это могут быть как автоматические ограничения (на примере задач в Stash), так и дополнительный "ручной" контроль со стороны человека, который занимается мержем. Ну и дисциплина самих разработчиков: если Вася сообщил о проблеме в коде, он не должен тут же ставить аппрув.

Как создать репозиторий и скопировать туда свои готовые файлы?

Решил обезопасить себя и закинуть проект в git, конкретно на bitbucket. Git установлен, но пользовался до этого только "pull-push" Есть папка с проектом которую мне надо закинуть, в мануале написано:
mkdir /path/to/your/project
Мне там нужно прописать название папки или же полный путь до папки? Или же мне нужно что-то другое?
Может использовать инструкцию "У меня уже есть проект"? Если я буду закидывать свой проект, не закину ли я его случайно в аккаунт конторы в которой работаю?


Ответ

создайте в bitbucket новый репо (наверное, уже); скопируйте его SSH URL – что-то вроде git@bitbucket.org:drtvader/superproject.git – убедитесь, что там ваше, а не конторы имя после двоеточия; зайдите в папку вашего проекта у себя на компе; git init инициализирует git проект; git add . добавит в него все файлы и папки в текущей директории и глубже; git commit -m "initial commit" – закоммитит их все; git remote add origin git@bitbucket.org:drtvader/superproject.git – сюда подставляете скопированный во 2-м шаге URL вашего репо на Bitbucket; git push origin master чтобы закинуть свежесозданный коммит на bitbucket.
Всё, вроде бы. Веток и тегов у вас пока нет. С BitBucket вы уже работали с этого компьютера для вашей организации, поэтому дальнейшие замечания, скорее всего, не пригодятся:
A. может понадобиться ответить yes при первом подключении к BitBucket с вашего компа в 8-м пункте с git push.. - на вопрос о том, доверять ли такому-то сертификату от такого-то IP адреса.
B. если не пользовались раньше git'ом с этого компьютера, понадобится сконфигурить git – задать ваше имя латиницей и email – они будут указаны как автор коммитов с этого компа:
git config --global user.name Vassia Poupkin git config --global user.email poupkin@mail.ru
C. может быть, не все файлы вы захотите контролировать git'ом – например, конфиги с паролями – заранее создайте файл .gitignore и занесите их названия туда, по одному на строке, чтобы git не обращал на них внимание.
D. создайте в корне проекта файл README.md в разметке Markdown с описанием вашего проекта, его названием и почётными копирайтами – содержание этого файла BitBucket покажет на странице вашего проекта.

PostgreSQL - psql: пользователь “Washington” не прошёл проверку подлинности (по паролю)

Установил PostgresSQL. В консоли Windows ввожу команду psql и получаю приглашение к вводу пароля. Перепробовал все пароли, какие я только могу использовать - ничего не помогает.
Сначала я подумал, что нужен пароль, который я определил при установке БД. Не прошел. Увидел сообщение (в названии темы) и подумал, что раз говорит о пользователе системы Washington, то нужен пароль пользователя системы. Не прошел. Ну затем перепробовал все пароли которые приходили на ум ))


Ответ

почему-то по умолчанию psql использовал не имя заданное при инсталляции, а имя пользователя системы.. в данном случае надо явно указать имя заданное при инсталляции - psql -U yourname

Как сделать вот такой вот таймер в картинку?

Дело в том что она генерируется через php. Вопрос как такое реализовать?


Ответ

Просто GIFка, которая генерируется при открытии. Проверить можно разобрав её на части.
Вот пример на PHP (почему вы решили, что mail.ru генерирует его на php?): Image only Countdown Clock или ссылка на github

Конвертация кода C# => VB.NET

День добрый. Переписывал библиотеку с C# на более удобный для себя VB.NET и не смог разобраться как написать два куска кода.
Код 1.
throw new RucaptchaErrorException((RucaptchaError)Enum.Parse(typeof(RucaptchaError), str.Substring(6)));
Попытка получить хоть какой то код через декомпилятор выглядит так:
Throw New RucaptchaErrorException(DirectCast(Enum.Parse(GetType(RucaptchaError), Str.Substring(6)), RucaptchaError))
Код 2.
public object Clone() { var paramsContainer = new ParamsContainer(); foreach (var obj in from object index in Params.Keys select (Param) Params[index]) paramsContainer.Params.Add(obj.Key, obj); return paramsContainer; }
При попытке конвертнуть этот метод, у декомпилятора вообще снесло крышу и получившийся кусок даже не стоит приводить.
Прошу помощи.


Ответ

Код 1:
Throw New RucaptchaErrorException(DirectCast(System.Enum.Parse(GetType(RucaptchaError), str.Substring(6)), RucaptchaError))
Код 2:
Option Infer On
Public Function Clone() As Object Dim paramsContainer = New ParamsContainer() For Each obj In From index As Object In Params.Keys Select CType(Params(index), Param) paramsContainer.Params.Add(obj.Key, obj) Next obj Return paramsContainer End Function
p.s. могут быть ошибки, использовал конвертер: http://www.tangiblesoftwaresolutions.com/Free_Edition_Downloads/Instant%20VB%20(Free%20Edition)%20Setup.exe

Как правильно пересоздать закэшированный Observable используемый вместе с Retrofit?

Дано:
API, возвращающее список с данными в формате JSON
Задача:
Получить эти данные силами Retrofit+RxJava
Проблема:
Необходимо сделать изначально один запрос и не дублировать его, если экран будет повёрнут до окончания задачи. Также нужно иметь возможность перезапустить задачу.
Что получилось:
Первое я решил, сделав Singlton и закешировав единственный экземпляр Observable с помощью cache().
Второе - полным пересозданием объекта Retrofit (1), экземпляра retrofit-интерфейса (2) и самого Observable(3). Если 1 и 2 не сделать - 3 - остаётся прежним и возвращает закэшированные данные, вместо новых.
Вопрос:
Использованный мной способ перезапуска задачи получения данных выглядит плохо. Как лучше/правильнее пересоздать Observable?

Синглтон для получения/пересоздания Observalbe
public class SingltonRetrofit { private static RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io());
private static Gson gson = new GsonBuilder().create();
private static Retrofit retrofit = new Retrofit.Builder() .baseUrl(Const.BASE_URL) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(rxAdapter) .build();
private static GetModels apiService = retrofit.create(GetModels.class); private static Observable> observableModelsList;
public static void reset() { retrofit = new Retrofit.Builder() .baseUrl(Const.BASE_URL) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(rxAdapter) .build(); apiService = retrofit.create(GetModels.class); observableModelsList = null; }
public static Observable> getModelsObservable() { if (observableModelsList == null) { observableModelsList = apiService.getModelsList().cache(); } return observableModelsList; } }
P.S.
Этот же вопрос на английском: How to recreate or reset cached Observable, used with Retrofit to get new data?


Ответ

В итоге сделал так:
Как верно написал @mit, метод cache() кэшировал запрос и пересоздание observable в итоге не перезапускало сетевой запрос. При этом в доках и в интернетах я нигде сему упоминания не находил. Видать это как-то связано с внутренней логикой связки Retrofit+OkHttp При этом как верно предложил @Yura Ivanov, потребовался BehaviorSubject На него подписывается фрагмент и его же можно пересоздать в случае нужды в свежих данных (без пересоздания будет отданы последние данные). При этом при каждом создании/пересоздании BehaviorSubject создаётся Subscriber для получения данных из сети через Observable, создаваемый Retrofit-ом. И он в onError и в onNext вызывает соответствующие методы у BehaviorSubject. При этом не транслируя onComplete, т.к. в этом случае может произойти ситуация, когда данные придут в процессе пересоздания фрагмента и фрагмент получит только последнее событие BehaviorSubject, т.е. событие завершения последовательности, вместо последних полученных данных. Т.е. соединять подпиской напрямую BehaviorSubject и Observable, получающий сетевые данные не стоит. Итого все требования соблюдены: При поворотах экрана будет запущена всего однажды задача на скачивание данных, фрагмент получит данные (или сообщение об ошибке) в любом случае и пересоздавать объекты Retrofita-а не нужно.
Итоговый синглтон:
public class SingltonRetrofitNew { private static RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io());
private static Gson gson = new GsonBuilder().create();
private static Retrofit retrofit = new Retrofit.Builder() .baseUrl(Const.BASE_URL) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(rxAdapter) .build();
private static GetModels apiService = retrofit.create(GetModels.class);
private static BehaviorSubject> observableModelsList; private static Observable> observable = apiService.getModelsList(); private static Subscription subscription;
private SingltonRetrofitNew() { }
public static void resetObservable() { observableModelsList = BehaviorSubject.create();
if (subscription != null && !subscription.isUnsubscribed()) { subscription.unsubscribe(); } subscription = observable.subscribe(new Subscriber>() { @Override public void onCompleted() { //do nothing }
@Override public void onError(Throwable e) { observableModelsList.onError(e); }
@Override public void onNext(ArrayList hotels) { observableModelsList.onNext(hotels); } }); }
public static Observable> getModelsObservable() { if (observableModelsList == null) { resetObservable(); } return observableModelsList; } }
Сокращённый фрагмент:
public class FragmentsList extends Fragment { private static final String TAG = FragmentList.class.getSimpleName(); private Subscription subscription; private RecyclerView recyclerView; private SwipeRefreshLayout swipeRef; private ArrayList models = new ArrayList<>(); private boolean isLoading;
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment, container, false); //init views recyclerView = (RecyclerView) v.findViewById(R.id.recycler); swipeRef = (SwipeRefreshLayout) v.findViewById(R.id.swipe_ref); swipeRefreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh() { SingltonRetrofitNew.reset(); getModelsList(); } });
if (savedInstanceState != null) { models = savedInstanceState.getParcelableArrayList(Const.KEY_MODELS); isLoading = savedInstanceState.getBoolean(Const.KEY_IS_LOADING); }
if (models.size() == 0 || isLoading) { getModelsList(); } //TODO show saved data if is
return v; }
@Override public void onDestroy() { super.onDestroy(); if (subscription != null && !subscription.isUnsubscribed()) { subscription.unsubscribe(); } }
private void getModelsList() { isLoading = true; swipeRef.setRefreshing(true); if (subscription != null && !subscription.isUnsubscribed()) { subscription.unsubscribe(); } subscription = SingltonRetrofitNew.getModelsObservable(). subscribeOn(Schedulers.io()). observeOn(AndroidSchedulers.mainThread()). subscribe(new Subscriber>() { @Override public void onCompleted() { Log.d(TAG, "onCompleted"); }
@Override public void onError(Throwable e) { Log.d(TAG, "onError", e); isLoading = false; swipeRef.setRefreshing(false); Snackbar.make(recyclerView, R.string.connection_error, Snackbar.LENGTH_SHORT) .setAction(R.string.try_again, new View.OnClickListener() { @Override public void onClick(View v) { SingltonRetrofitNew.reset(); getModelsList(); } }) .show(); }
@Override public void onNext(ArrayList newModels) { isLoading = false; swipeRef.setRefreshing(false); models.clear(); models.addAll(newModels); //TODO show data } }); }
@Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelableArrayList(Const.KEY_MODELS, models); outState.putBoolean(Const.KEY_IS_LOADING, isLoading); } }
Всё вместе на gitHub: RxRetrofitAndScreenOrientation
Статья на ХабраХабр про решение: Используем RxJava и Retrofit на Android, учитывая поворот экрана