Страницы

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

суббота, 29 декабря 2018 г.

Разименование итератора в std::set

Доброго времени суток! Я недавно начал заниматься программированием и сейчас возникла потребность в рассмотрении контейнера std::set(далее именуемый контейнер). И у меня возникло несколько вопросов, поискав в интернете не нашел подходящих ответов, решил спросить у знающих людей, которые могли бы помочь мне. И так суть вопроса, имеется контейнер типа const char* в который мы добавляем 2 элемента. typedef std::tr1::unordered_set unordered_set; unordered_set myUnorderedSet; myUnorderedSet.insert("testAction"); myUnorderedSet.insert("testActionTwo"); далее если пробежаться по контейнеру for ( unordered_set::iterator it = myUnorderedSet.begin(); it != myUnorderedSet.end(); ++it ) { std::cout << " " << *it; std::cout << std::endl; } можно вывести значения хранящиеся в данном контейнере. Затем я пытаюсь найти нужное мне значение используя метод find(). unordered_set::iterator = myUnorderedSet.find("testAction"); Как получить значение данного итератора, для того чтобы можно было сравнить его со значение которое я добавлял в контейнер*? И почему при такой записи *iter я получаю ошибку компиляции: list iterator is not dereferencable. Не совсем понимаю, ведь for ( unordered_set::iterator it = myUnorderedSet.begin(); it != myUnorderedSet.end(); ++it ) { std::cout << " " << *it; std::cout << std::endl; } мы можем применить операцию разыменования. Заранее благодарен за ответы!


Ответ

смотрим описание метода find() тут(ru) или тут(en) и видим что если find ничего не находит то возвращает итератор на end(), то есть на элемент следующий за последним и он (итератор end()) действительно не разыменуемый (is not dereferencable) то есть имея массив из 5 элементов [0,1,2,3,4] find ненайдя ничего вернёт [5] то есть end() соответственно для проверки "а нашлось ли чего нибудь" сравниваем if(iterator==myUnorderedSet.end()) почему так происходит? в set'e вы храните не строку testAction а указатель на неё и в функции find() сравниваются указатели! когда вы пишите строку в хардкоде то она помещается в специально отведённое место в программе, а вместо неё используется указатель на это место, написав два раза одинаковую строку testAction получаем две строки в специально отведённом месте (НО компиляторы могут с оптимизировать такие строки, в итоге имеем UB) как сравнивать строки? в STL есть тип данных(class) для строк string пихаем строки в стринг и при сравнении будет происходить преобразование string str="hello world";// или string str("hello world"); if(str=="hello world")//TRUE

Кэширование лямбда-выражений C#

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


Ответ

Лямбда-выражение — не более чем хитро оформленный указатель на функцию, так что кешированием вы не добьётесь ощутимого выигрыша в производительности. Не пытайтесь ускорить программу, не проведя профилирование. По поводу второго прогона — думаю, вы столкнулись с JIT-компиляцией. Каждая функция (не только лямбда) при первом выполнении компилируется в нативный код. Каждое последующее выполнение уже не нуждается в компиляции, а значит, происходит значительно быстрее.

Что такое dns-prefetch и x-dns-prefetch-control

Привет. Решил подробнее изучить тему мета-тэгов и наткнулся на такие тэги: Скажите как работают и какую задачу решают. Спасибо.


Ответ

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

Что не так в моем коде, и как подтянуть навыки?

Отправил тестовое задание на позицию Android разработчика, но в ответ они написали: После ознакомления с тестовым заданием, мы отметили, что у вас недостаточный уровень знания принципов ООП и принципов построенийAndroid-приложений. Если вы подтянете свой уровень знаний, лучше изучите ООП и каким образом применять его принципы для построения приложений, то мы могли бы вернуться к вопросу рассмотрения вашей кандидатуры в будущем. Я самоучка, учился по книгам, статьям и т.д. , можете опытным глазом посмотреть что в моем коде не так в плане ООП и принципов построения? И как апргрейдить эти навыки? Код на gitHub, т.к. классов не один и не два https://github.com/Vlad161/Products


Ответ

Ответ работодателя очень похож на стандартную отписку, поэтому не стоит воспринимать его буквально. После просмотра вашего проекта (кстати, неплохо было бы написать, что именно от вас хотели, можно выдержку из тестового задания) остались такие замечания:
Имена классов. Обычно имена классов - существительные (JSONReadFromAsset стоило бы назвать JSONAssetReader). К тому же стоит придерживаться какого-то общего стиля именования (два класса-активити заканчиваются на Activity, третий почему-то нет). Скорее всего от вас ждали минимальной реализации MVC. Стоило создать bean для хранения сведений о продукте и добавить уровень абстракции DAO для извлечения данных из файла. Как-то так:

public interface ProductDAO { List getProducts(); }
public class ProductDaoImpl implements ProductDAO { public List getProducts() { // здесь вытаскиваем список продуктов из JSON } }

Таким образом вы бы отделили реализацию получения данных от логики их обработки, получив возможность изменять способ получения данных, не затрагивая основную логику программы.
Насчёт "подтянуть навыки ООП" - читайте Head First Design Patterns и GOF

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

Доброго времени суток. Как переименовать существующую БД с помощью sql запроса из php?


Ответ

Сделайте бэкап всей исходной БД. RENAME TABLE позволяет переименовывать таблицы из одной БД в другую, при условии, что обе БД находятся на общей файловой системе. Так что надо создать новую БД, переименовать таблицы из старой в новую: CREATE DATABASE db_new;
RENAME TABLE db_old.table1 TO db_new.table1, db_old.table2 TO db_new.table2, ... db_old.tableN TO db_new.tableN ; Проверьте, перенеслись ли таблицы, осталось ли что-то нужное в старой БД. Удалите старую БД: DROP TABLE db_old;

Как вырезать угол блока с помощью CSS3?

Необходимо вырезать все углы блока с помощью CSS3. Как на картинке


Ответ

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

'ов с отключенной прокруткой, которые содержат 'ы, тени, границы и псевдо-селекторы.
Вот основной HTML и CSS для начала:
a {display:inline-block; width:250px; height:100px; background:#ccc; border:2px solid #000; position:relative; margin:10px;} a div {position: absolute; top: 0; overflow: hidden; width: 15px; height: 100%;} a div:after {content:''; background:#000; width:2px; height:75px; position:absolute; top:12.5px;} a div:first-of-type {left: -14px;} a div:first-of-type:after {left:0;} a div:last-of-type {right: -14px;} a div:last-of-type:after {right:0;} a span {display:block; width:30px; height:30px; background:transparent; position:absolute; bottom:-20px; right:-20px; border:2px solid #000; border-radius:25px; box-shadow:0 0 0 60px #ccc;} a div:first-of-type span {left:-20px;} a div:first-of-type span:first-child {top:-20px;} a div:first-of-type span:last-child {bottom:-20px;} a div:last-of-type span {right:-20px;} a div:last-of-type span:first-child {top:-20px;} a div:last-of-type span:last-child {bottom:-20px;}

Это перевод ответа «Inset border-radius with CSS3».

Красивый вывод var_dump

Что нужно изменить в php.ini, для того чтобы иметь человекочитаемый вывод, например, var_dump и print_r? Сейчас всё выводиться в один ряд, читать массивы с данными нереально.


Ответ

echo '

'; 
var_dump($smth);
print_r($array); 
echo '
';
Обновление
function vardump($var) { echo '
';
  var_dump($var);
  echo '
'; }
Использовать вместо var_dump. ))

Логирование ошибок

Здравствуйте! Не подскажете, каким способом логировать ошибки в Android-приложениях? Каким способом лучше отправлять с аппарата на сервер разработчика сообщения об ошибке в приложении? Я думаю, что стоит писать все в файл и отправлять на сервер через время, если есть необходимость. Но как отловить все ошибки в приложении, пока не знаю. Что можете посоветовать?


Ответ

Для отлова есть библиотека Acra. Отлавливает абсолютно всё + есть возможность для отправки баг репорта программисту-создателю. Вот мини-гайд А для логирования slf4j, правда, как она дружит/недружит с андроидом, я хз.

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

Собственно сабж: есть директория, которую вводит юзер, но она может не существовать в системе (соотвествено если она не существует, я ее создаю). File.isDirectory возвращает true, только если эта директория существует. Как еще можно проверить?


Ответ

Так нельзя проверить является ли строка директорией. Это проверка на существование, если не существует он вернет fakse. А как мне проверить что директория например /home/user/somedir/ является путем, даже если этой директории у меня нет на компе ? Никак. Т.к. до момента создания файла/директории НЕИЗВЕСТНО, кто это на самом деле будет. Попробуй создать файл без расширения в одной папке и такую же директорию рядом с файлом. По крайней мере в NTFS это невозможно. Отсюда вывод: до того как создан файл/директория, ты не узнаешь, кто это на самом деле.

Последовательное чтение значений из списка в словарь

Здраствуйте. Есть готовый список, который содержит слова в определенной последовательности: list = ['To', 'be', 'or', 'not', 'to', 'be'] Требуется подсчитать частоту появления слов в этом списке и составить словарь, который содержит пары значений (слово) : (кол-во повторений этого слова). Вот мой код: # -*- coding: utf-8 -*-
list = ['To', 'be', 'or', 'not', 'to', 'be']
counts = dict() for word in list: if word not in counts: # Если символа нет в словаре, создаем новую запись counts[word] = 1 else: # В противном случае инкрементируем d[c] counts[word] += 1
print counts Подсчет слов ведется правильно. Проблема в том, что моя программа помещает новые записи в словарь в хаотичном порядке, а не так, как слова шли в предложении. Вот что интерпретатор выдает на выходе: {'not': 1, 'To': 1, 'or': 1, 'to': 1, 'be': 2} А должно быть так: {'To': 1, 'be': 2, 'or': 1, 'not': 1, 'to': 1} Как можно получить такой результат? Никак не могу монять. P.S.: В Python я новичок, поэтому не судите строго.


Ответ

Вам нужен OrderedDict, Dict не поддерживает упорядочивание записей по умолчанию.

Когда в c# class не совсем class?

В одном проекте разбирал багу. Эта бага была связана с тем, что проект прошел некоторую техническую итерацию, т.е. бизнес логика в нём не поменялась, но в него была добавлена технология, которая неявно поменяла поведение кода, оставив его представление неизменным. И связано это именно с тем, что в некоторых случая class бывает не совсем class-ом. Лабораторная по анализу этого бага приобрела форму задачки на знание технологии .NET. Таким образом, прошу оценить формулировку задачки и её актуальность. Ну, и если захотите, можете представить её решение. :)
Задачка
Есть код консольного приложения на c#:
#region Здесь код изменять нельзя public sealed class ClassA { private int _value;
public int Value { get { return _value; } set { _value = value; } } } #endregion
#region Здесь код изменять нельзя public sealed class ClassB #endregion #region Здесь код изменять нельзя { public void Do(ref ClassA a) { a.Value = 5; } } #endregion
public class Program { public static void Main(string[] args) { #region Для класс Program изменять код только здесь ClassB b = new ClassB(); #endregion
bool result = Process(b);
System.Console.WriteLine(result); }
public static bool Process(ClassB b) { ClassA a1 = new ClassA(); ClassA a2 = a1;
b.Do(ref a2);
return a1.Value == a2.Value; } }
Запустив его на исполнение мы увидим, что метод Program.Process вернёт значение true и на консоль будет выведен текст «true».
Используя стандартный функционал .NET Framework (версией >= 2.0) допишите код для классов ClassA и ClassB, а также измените код в методе Program.Main, чтобы метод Program.Process вернул значение false и, соответственно, на консоль должно быть выведено «false». Код в регионах #region Здесь код изменять нельзя менять нельзя. Для класса Program код можно поменять только в регионе region Для класс Program изменять код только здесь.
UPD Спасибо @DreamChild Директивы условной компиляции C# не применять.
UPD Хотел бы ещё раз уточнить, что нужно только дописать ClassA и ClassB, т.е. не нужно создавать новые классы.
UPD Ответ дал @hazzik Суть в том, что выполнение функционал класса ClassB перевели в другой домен. Но при этом неявно поменялась логика работы метода ClassB.Do(ref ClassA) и экземпляр типа ClassA уже передаётся не как ссылочный объект, а как значимый объект, т.е. в результате сериализации получается структура значений полей класса ClassA, которая передается через границу домена. При выходе из метода ClassB.Do(ref ClassA) возвращается структура полей класс ClassA и, самое интересное, эта структура десериализуется в новый объект, ссылка на который и записывается в переменную a2. Таким образом, в a1 и в a2 получаются ссылки на два разных объекта, при чём, значения их внутренних полей различаются.


Ответ

То же самое, что и предыдущий мой ответ, только все это делаем средствами .NET fx, т.е. используем его прокси и, соответственно, все вызываем из отдельного домена:
[Serializable] #region Здесь код изменять нельзя public sealed class ClassA { private int _value;
public int Value { get { return _value; } set { _value = value; } } } #endregion
#region Здесь код изменять нельзя public sealed class ClassB #endregion : MarshalByRefObject #region Здесь код изменять нельзя { public void Do(ref ClassA a) { a.Value = 5; } }
#endregion
public class Program { public static void Main(string[] args) { #region Для класс Program изменять код только здесь ClassB b = (ClassB) AppDomain.CreateDomain("X").CreateInstanceFromAndUnwrap(typeof(ClassB).Assembly.CodeBase, typeof(ClassB).FullName); #endregion
bool result = Process(b);
Console.WriteLine(result); }
public static bool Process(ClassB b) { ClassA a1 = new ClassA(); ClassA a2 = a1;
b.Do(ref a2);
return a1.Value == a2.Value; } }
Почему так происходит? ClassA не помечен для маршаллинга через границу доменов с передачей по ссылке (то, что делает MarshalByRefObject), по-этому он будет сериализован до передачи в домен "X" и в домене "X" десериализован в новый объект. Для внешнего домена никто никогда не изменял a1 его Value так и останется 0. При возвращении из домена "X" экземпляр класса ClassA будет сериализован и десериализован уже в обратном направлении и присвоен переменной a2
Если у параметра a метода ClassBDo убрать модификатор ref то картина будет немного иной: обратной десериализации из "X" в текущий домен происходить не будет, и, следовательно, a2 будет все-еще ссылаться на тот же объект, что и a1, а значение свойства Value этого объекта останется равным 0
Чтобы исправить эти "проблемы" нужно унаследовать ClassA от MarshalByRefObject

Поместить static/const в интерфейс или абстрактный класс C#

Как можно определить интерфейс или абстрактный класс, который вынудит реализовывать публичную константу (отображаемое пользователям наименование класса, нужно вывести список до того как юзверь тыкнет в заинтересовавший его класс) и статический метод (например GetInstance)?


Ответ

Никак.
Это не поддерживается языком.
Вы можете сэмулировать константу уровня экземпляра класса через свойство с одним лишь геттером:
interface ISomething { string ClassName { get; } }
Статические методы в интерфейс не вписываются никак, вообще. В текущей концепции вы получаете доступ к статическому объекту по имени класса, а не по экземпляру объекта. А поддержка интерфейсов реализована обычным образом, через таблицы виртуальных методов.
Тем не менее, в будущих версиях языка возможны изменения, разрешающие схожую функциональность (generic-условия на наличие статического метода). Design team языка C# обсуждает эту возможность.

Вот пример того, как динамически проверить наличие статического метода:
interface ISomething { }
static class SomethingChecker { public static Func CheckAndGetBuider() where T : ISomething { var type = typeof(T); var builder = type.GetMethod("GetInstance", BindingFlags.Public | BindingFlags.Static); // а есть ли такой метод? if (builder == null) throw new Exception(); // а не требует ли метод generic-аргумент? if (builder.IsGenericMethod) throw new Exception(); // а не требует ли метод параметров? if (builder.GetParameters().Length != 0) throw new Exception(); // а подходящий ли тип результата? if (!type.IsAssignableFrom(builder.ReturnType)) throw new Exception(); // все проверки пройдены return () => (T)builder.Invoke(null, null); } }
Здесь рабочий пример использованием: http://ideone.com/bPyoEf

StreamReader и кодировка

Допустим, у меня есть файл и у него может быть любая кодировка. Как с помощью StreamReader корректно прочитать данные из этого файла, чтобы потом записать их в другой файл с кодировкой UTF-8?


Ответ

Никак. Гарантировано рабочего решения не существует. Для того, чтобы работать с текстовым файлом, система обязана знать его кодировку.
Что вы можете попробовать:
Используйте StreamReader без указания кодировки. Он попробует продетектировать, и в нормальных случаях (а это означает обычно Unicode-кодировки) ему это удаётся. Попробуйте сдетектировать кодировку на основе частотного анализа. Если вам известен язык, на котором написан ваш текст, вы можете определить относительную частоту символов в текстах (это будет ожидаемое распределение частот), попробовать пооткрывать текст в кодировках, релевантных для этого языка (например, для русского языка это CP1251, CP866, KOI8-R и т. п.), и посмотреть, в какой из них распределение частот символов будет ближе всего к той самой относительной частоте. (Это реализовано, например, в редакторе Far Manager'а).
В ответах на этот вопрос есть несколько примеров с кодом, комбинирующих эти подходы.
В любом случае, на будущее: текст не имеет права храниться без кодировки. Текст без кодировки — никому не нужные данные. Всегда знайте кодировку, в которой лежит ваш текст.

Если же вы знаете кодировку файла, то всё гораздо проще:
var srcEncoding = Encoding.GetEncoding(1251); var dstEncoding = Encoding.UTF8;
using (var src = new StreamReader(srcFileName, encoding: srcEncoding)) using (var dst = new StreamWriter(dstFileName, append: false, encoding: dstEncoding)) { string line; while ((line = src.ReadLine()) != null) dst.WriteLine(line); }

Сформировать коммит с сообщением на основе указанного коммита

Задача следующая: нужно скопировать сообщение старого коммита и исправить последнюю строку в нём для нового коммита.
Сейчас приходится находить нужный коммит, копировать его сообщение, делать новый коммит с таким же сообщением, подправляя последнюю строку. Хочется упростить этот процесс.
Узнал недавно про такую возможность, как git commit -C HEAD, которая сделает коммит с таким же сообщением, как в указанной ссылке, но приходится еще делать git commit --amend, чтобы подправить последнюю строку.
Можно ли обойтись одной командой для этого?


Ответ

изспользуйте опцию -c, а не -C
git commit -c <коммит>
в этом случае сразу можно внести правки в коммит-сообщение.
ещё логично добавить опцию --reset-author, для того, чтобы авторство и время создаваемого коммита не дублировались из указанного существующего коммита.

Окно переменной длины и размещение контролов

Допустим, нужно создать окно с тестовыми вопросами. Неизвестно, какой длины будет окно. Как добавлять в такое окно элементы? Вроде с формой не поработаешь. В Qt есть менеджеры компоновки. Там просто добавляешь элементы. В С# есть что-нибудь подобное? Как в таком случае организовать добавление элементов окна?
UPD: Черт, простите, моя вина. Я пишу на WinForms и там уже относительно большой проект написан. Эти вопросы являются частью проекта, которую я оставил для реализации на потом. Так что решения WPF не требуются, хотя все равно спасибо за них, в будущем почитаю про них.


Ответ

Если вы используете WinForms, изучайте:
Свойства: Control.Anchor Control.Dock Control.Margin Control.Padding Классы: TableLayoutPanel FlowLayoutPanel SplitterPanel См.: Windows Forms Layout
Если вы используете WPF, изучайте:
Свойства: FrameworkElement.HorizontalAlignment FrameworkElement.VerticalAlignment FrameworkElement.Margin FrameworkElement.Padding Классы: Grid DockPanel StackPanel WrapPanel Canvas См.: Layout Alignment, Margins, and Padding Overview
В целом, WPF даёт больше свободы для дизайна, поэтому, если вам требуется сложная логика размещения контролов, рекомендуется использовать его. Ну и WPF — более современная и передовая библиотека, лучше поддерживает современные возможности и всё такое.

Обращение к функции заданной в __init__.py

Здравствуйте. При инициализации пакета в Python 2.7, мне нужно определить функции, которые должны быть общими для всех модулей данного пакета. Я определил их в __init__.py. Как теперь к ней обратиться внутри пакета? Извне получается так:
import package.module package.foo() #обращение
Внутри пакета (например в модуле module), не определено foo, dir(__package__) - так же не выводит этой функции.
Структура проекта:
package\ # пакет __init__.py # здесь функция module.py # здесь мне функцию нужно вызвать
Названия, естественно, отличаются.


Ответ

Исправлено
На самом деле, файл __init__.py не предназначен для хранения реализации общих для пакета функций. Их предлагается выносить в другие файлы.
Вот что говорится в документации
<...> In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.
Цитата с python-guide.org
<...> special behavior for the __init__.py file, which is used to gather all package-wide definitions. <...> Leaving an init.py file empty is considered normal and even a good practice, if the package’s modules and sub-packages do not need to share any code. Lastly, a convenient syntax is available for importing deeply nested packages: import very.deep.module as mod. This allows you to use mod in place of the verbose repetition of very.deep.module.

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

Например, если у вас сейчас есть функция boo в файле __init__.py, вы можете вынести её в файл module.py, при необходимости вынеся её на уровень пакета, добавив следующую строку в ваш файл __init__.py
# файл package/__init__.py from module import boo
и для внешнего кода, импортирующего ваш модуль, она станет доступна не только через прямой импорт
# файл my_script.py from package.module import boo
но и через импорт из пакета:
# файл my_script.py from package import boo # та же функция

Источники:
Документация Объяснение использования файла __init__.py python-guide.org

Подсчет совпадений разных значений в mysql

В mysql ведётся лог недоступности оборудования. Встала задача считать, сколько раз оборудование "падало" в заданном интервале. Структура таблицы такая:
+-------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+-------------+------+-----+---------+----------------+ | id | int(20) | NO | PRI | NULL | auto_increment | | ip | varchar(15) | NO | | NULL | | | power_state | varchar(10) | NO | | NULL | | | power_time | int(10) | NO | | NULL | | +-------------+-------------+------+-----+---------+----------------+
На данный момент подсчитываю количество падений весьма извращенным способом (получаю список ip из другой таблицы и делаю запрос в эту) Понимаю, что можно сделать как-то по человечески, но как - не могу придумать..
$query="SELECT * FROM `device_data` WHERE `visible` = '1'"; //список ip $result = mysql_query($query) or die(mysql_error()); for ($c=0; $c '$datefrom' AND `power_time` < '$dateto'"); $num_rows = mysql_num_rows($down_query);
echo " $ip $num_rows "; }
Как результат - задача выполнена, но долго. Помогите оптимизировать, либо пните в нужную сторону.


Ответ

1. JOIN
В принципе, про джойн уже написали. Это должно быть на автомате - если запрос в цикле, то джойн. Делается он совсем несложно - берутся две таблицы и связываются по общему полю:
SELECT ip FROM power_data p, device_data d WHERE p.ip=d.ip
и вот мы уже получили сводную таблицу, в которой к первой дописаны данные из второй, подтянутые по ip=ip (причем из первой данные не берутся, если во второй нет связи. За это отвечает тип джойна). Дальше к этому запросу можно дописывать любые операторы как обычно. d и p - это алиасы, для сокращения писанины.
2. GROUP BY
Теперь GROUP BY. Это ведь совсем несложно. Сгруппировать по одинаковым IP и попросить базу посчитать количество вхождений по ним. То есть - получить ровно те данные, которые нам нужны: ip - цифра, ip - цифра...
Причем сделано это будет внутри самой БД, без необходимости гонять все данные между скриптом и базой:
SELECT p.ip, count(1) cnt FROM power_data p, device_data d WHERE p.ip=d.ip AND p.power_state=0 AND d.visible = 1 AND p.power_time > [datefrom] AND p.power_time < [dateto] GROUP BY p.ip
EXPLAIN и индексы.
Здесь без готовой базы (причем заполненной данными - это важно), получить правильную аналитику не получится. Генерить тестовые данные - настолько далеко мой альтруизм не распространяется. Но обычно оптимизация запросов - это отдельный вопрос, который автору велят задавать отдельным постом, включив все запросы, а так же вывод команды, которую надо скопировать 1-в-1 и выполнить в консоли или phpmyadmin
3. EXPLAIN [тестируемый запрос]
Но в принципе можно дать пару рекомендаций и так: Надо смотреть в колонки key - актуально задействованный ключ, и rows - количество затронутых запросом строк. Причем надо перемножить между собой все цифры из этой колонки. В колонке key должно быть хоть что-то, а в колонке rows - как можно меньшее число.
Если наугад, чисто из опыта - то в device_data для этого запроса пригодился бы индекс по ip,visible, а в power_data - по power_state,power_time
Эти первые три пункта - главное. С них должна начинаться любая оптимизация и именно они дадут принципиальный прирост производительности, пренебрегать ими нельзя.
4. Мелкие оптимизации
Идея сократить размер данных в таблице - здравая. В первую очередь она касается самого IPv4 адреса, который представляет из себя ничто иное, как обычный 4-байтовый int. И может храниться в колонке соответствующего типа. Для конвертации в mysql есть функции inet_aton() и inet_ntoa() Разумеется, никаких проблем с WHERE эти функции не создают. Ну, то есть, если самому не тупить и не писать WHERE inet_ntoa(ip) = '127.0.0.1', применяя функцию к каждой записи в таблице. Применять её надо к константе, оставляя поле как есть:
WHERE ip = inet_aton('127.0.0.1')
и индекс будет работать прекрасно.
Также можно вместо слов писать в статусы цифры, и таким образом сократить размер всей записи до 16 байт!
5. PDO
Как говорилось выше и все время говорится на всех сайтах и форумах, надо от от функций mysql переходить к использованию PDO preparеd statements. Это даст сразу ТРИ эффекта:
пропадут любые ошибки, вызванные неверными данными. SQL-инъекции окажутся на свалке истории*) (о чем чаще всего не знают) множество рутинных операций станут выполняться проще и меньшим количеством кода.
Главное правило при работе с PDO - все запросы, в которых используются какие-либо переменные, должны выполняться строго через prepare()/execute(), а вместо переменных в запрос должны вставляться пейсхолдеры:
$stmt = $pdo->prepare("SELECT inet_ntoa(p.ip) ip, count(1) cnt FROM power_data p, device_data d WHERE p.ip=d.ip AND p.power_state=0 AND d.visible = 1 AND p.power_time > ? AND p.power_time < ? GROUP BY p.ip"); $stmt->execute(array($datefrom, $dateto)); $stats = $stmt->fetchALL(PDO::FETCH_KEY_PAIR);
в результате мы получим массив вида [ip => cnt] который очень удобно потом вывести в шаблоне:
?> $cnt)

*) утверждение не совсем верно, поскольку есть случаи, в которых PDO не справляется

PS. Вот меня часто ругают за то отношение, которое я высказываю по отношению к сообществу пхп в целом, и к тем его представителям, которые отвечают на вопроса на SO.
Ну скажите, какое может быть отношение, если три ответа, из которых
один переливает из пустого в порожнее: спросив, не ip ли v4 хранится в базе (как будто в варчар(15) можно запихнуть ipv6), потом, когда читатель ждёт уж рифмы "INT"... предлагает тот же варчар, только в профиль. Плюс немасштабируемый IN. Плюс куча мелкой непринципиальной косметики, причем не видно различия между действительно важными вещами и мелочевкой. а другие два смогли-таки в джойн, но груп бай уже не осилили.
Потом в вопрос придут добрые самаритяне, исправят "несправедливо" проставленные минусы, и все останутся довольны, а на просторах сети останется еще одна бессмысленная страница.

Загрузить изображение в GoogleDrive

При загрузке изображения в google drive иногда он загружается нормально памяти хватает, но иногда вываливает java.lang.OutOfMemoryError: Failed to allocate a 63489036 byte allocation with 16777216 free bytes and 21MB until OOM в коде я декодирую его в изображение переворачиваю изображение если надо будет, и указываю content type и загружаю в Google Drive. Ошибка выходит при декодировании изображения. Как можно это обойти, мне обязательно нужно загружать изображение не обрезанное и полное.
BitmapFactory.Options bmOptions = new BitmapFactory.Options(); Bitmap image = BitmapFactory.decodeFile(mSettings.getString(Const.directory, "") + "/" + file.getName(), bmOptions); if (Picture.getCameraPhotoOrientation(file) !=0) { image = Picture.rotateBitmap(image, 270); } OutputStream outputStream = result.getDriveContents().getOutputStream(); ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream); try { outputStream.write(bitmapStream.toByteArray()); } catch (IOException e1) { log(e1 + ""); } MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder().setMimeType("image/jpeg").setTitle(file.getName()).build(); DriveFolder folder = Drive.DriveApi.getFolder(mGoogleApiClient, DriveId.decodeFromString(stringFolderId)); folder.createFile(mGoogleApiClient, metadataChangeSet, driveContents).setResultCallback(fileCallback1);


Ответ

Это известная проблема возникающая при декодировании битмапа из файла. Проблемная строка BitmapFactory.decodeFile()
Чтобы ее решить, на старых версиях Android'а (до KitKat), достаточно было указывать битмап выгружаемым на диск:
BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inPurgeable=true;
Для новых версий - этот фокус уже не работает и приходится извращаться по другому, например:
BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inPreferredConfig = Config.RGB_565; //отводит на пиксель 2 байта, вместо 4-х по умолчанию bmOptions.inDither = true;
В итоге размер битмапа сокращается в 2 раза.
Update
Судя по логам у вас слишком большой размер битмапа (>60 мегов) - это очень много, явно больше разрешения девайса. Соответственно при декодировании я бы его смасштабировал, например так:
bmOptions.inSampleSize=4; //уменьшит размеры в 4 раза
то есть занимаемая память уменьшится в 16 раз, до 16 мегов. Если не поможет, то надо увеличивать до 5 или 6.
Почитайте эту статейку

Получить id пользователя VK

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


Ответ


Чтобы получить доступ к АРІ нужно зарегистрировать свое приложения.

Как делается псевдографический интерфейс в консоли?

Решил создать консольный файловый менеджер и оформить его наподобие FARa.
Какие функции и библиотеки надо использовать, да и с чего вообще нужно начинать?


Ответ

Вам нужны функции управления консолью. Поскольку C++ предоставляет лишь потоковый ввод-вывод (а этого не достаточно для ваших целей), вам придётся отказаться от использования cin/cout, и управлять консолью напрямую.
Здесь, к сожалению, вам придётся разделить ваш Windows- и Linux-специфический код.
Под Windows вам нужны консольные функции WinAPI. Наверное, проще всего будет просто напрямую обращаться к консольному буферу, который предоставляет символы на экране как просто прямоугольный массив из символов и их атрибутов.
Под Linux- (и вообще Unix-)платформой вам понадобится библиотека ncurses, которая предоставляет аналогичную функциональность.
Если вы пишете кроссплатформенную программу, вам придётся сделать уровень абстракции над системно-зависимыми библиотеками, и работать с ним в основной программе.
Удачи!

В каких случаях компиляторы оптимизируют код?

Вопрос про инициализацию стандартных типов. Например:
float fl_val; fl_val = 1.0f; fl_val = 1.0; fl_val = 1;
Здесь мы инициализируем float разными значениями. Понимают ли сейчас компиляторы (например, GCC и Visual Studio), что происходит, и оптимизируют эти моменты? Например, сразу приводят к float на этапе компиляции, а не во время выполнения: сначала int(1) приводят к (1.0f). Затраты небольшие, но есть. Вопрос с условием такого типа:
int a; // пусть она инициализирована неизвестным значением int b = a >= 0 ? 1 : 2 * 10;
* 10 относится только к условию false, или к true тоже? Проверить сейчас возможности нет.


Ответ

1) Да, компиляторы уже давно очень-очень умные в плане оптимизации. Они прекрасно оптимизируют все константы, до которых могут дотянуться. Вот вам пример с gcc: вот такая функция
#include
void f() { float f = 4; printf("%f", f); }
компилируется в следующее:
.LC1: .string "%f" f(): pushq %rbp movq %rsp, %rbp subq $16, %rsp movl .LC0(%rip), %eax movl %eax, -4(%rbp) cvtss2sd -4(%rbp), %xmm0 movl $.LC1, %edi movl $1, %eax call printf leave ret .LC0: .long 1082130432
Вы видите созданную константу .LC0 = 1082130432. Это есть битовое представление 4.0f, в чём легко убедиться: вот такой код
#include using namespace std;
int main() { union { int32_t l; float f; }; f = 4; cout << l; return 0; }
выдаёт в точности 1082130432.
2) Ну это же легко проверить, есть гора онлайн-компиляторов. Например: http://ideone.com/GJHdaH выдаёт ответ 1, то есть, умножение имеет более высокий приоритет.
int a = 1; int b = a >= 0 ? 1 : 2 * 10; cout << b;
Вы можете подсмотреть приоритеты в стандарте или в документации вашего компилятора, но для обычных целей простого эксперимента достаточно: вряд ли в имплементации компилятора такая дыра!
Важное «но»: если у вас возникли вопросы, такие же вопросы возникнут и у читателей вашего кода. Поэтому не поленитесь расставить скобки, чтобы смысл вашего кода не вызывал вопросов. Не надейтесь, что все остальные держат в голове таблицу приоритетов операций, тем более что в разных языках она разная. Для хорошего, долгоживущего кода очень важна читаемость.

Как сделать непрямоугольное окно?

Я видел приложения, окна которых имеют какую-то фантастическую форму.
Вопрос: как сделать окно произвольной формы в Windows 7 на Си?


Ответ

Я знаю такие способы:
С помощью функцииSetWindowRgn
Простой способ Окно будет "прозрачным" для событий мыши, т.е. не будет реагировать на нажатия мыши в прозрачных областях Не поддерживает альфа блендинг (края будут рваные)
С помощью расширенного стиля WS_EX_LAYERED
Поддерживает попиксельный альфа-блендинг или хромакей Более сложен в использовании, если нужен попиксельный альфа-блендинг
При использовании WS_EX_LAYERED, прозрачные пиксели (хромакей) можно устанавливать так:
SetLayeredWindowAttributes(m_hWnd, RGB(R,G,B), 0, LWA_COLORKEY);
Естественно, по WM_PAINT вы должны заливать прозрачные области тем же цветом.
Если вам нужен попиксельный альфа-блендинг, окно нужно отрисовывать не по WM_PAINT, а особым методом с использованием функции UpdateLayeredWindow (пример). Но есть и подводные камни - по RDP окно отображаться не будет. В этом случае нужно делать fallback на хрома-кей.

Как закрыть Activity?

При вызове метода onItemClick нужно закрыть текущую Activity В closeActivity() через this.finish() почему-то Activity закрыть нельзя. Для этого я создал еще один метод, в котором пытаюсь ее закрыть. Но в результате Activity переходит в "спящий режим" и остается в стеке Activity В чём ошибка?
Код методов (сразу с привязкой слушателя к ListView):
lvMain.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { Intent i = new Intent(SelectDictionary.this, MainActivity.class); startActivity(i); closeActivity(); } });
private void closeActivity() { this.finish(); }


Ответ

Согласно тык и документации
В манифесте, в объявлении вашей MainActivity добавляем
android:noHistory="true" Теперь покидая эту активити (любым способом, в т.ч. запуская новую) она сама вызывает свой finish() и удаляется из стека активити

Чекбокс “Выбрать все” выбирает все чекбоксы, и наоборот

При выборе главного checkbox'а выбираются все остальные, привязанные к нему, и наоборот, при выборе всех привязанных выбирается и главный.
Реализовать необходимо так, чтобы можно было использовать несколько групп на странице в пределах одной формы.
Поэтому сейчас реализовано так: у главного checkbox'а есть id, который совпадает с классами зависимых checkbox'ов. Классы могут быть любые - главное что они совпадают с id главного checkbox'а.
Рабочий код можно посмотреть ниже, но он слишком массивный. Есть ли более элегантные решения, желательно легко модифицируемые?
$(document).on("change", "input[type=checkbox]", function() { // По изменению checkbox'а if ($(this).attr('class')) { var CBgroupID = $(this).attr('class'); } if (($(this).attr('id')) && ($('input[type="checkbox"].' + $(this).attr('id')).length)) { var CBgroupID = $(this).attr('id'); if (this.checked) { $('input[type="checkbox"].' + CBgroupID).attr('checked', 'checked'); $('input[type="button"][class*="' + CBgroupID + '"]').removeAttr('disabled'); } else { $('input[type="checkbox"].' + CBgroupID).removeAttr('checked'); $('input[type="button"][class*="' + CBgroupID+'"]').attr('disabled', 'disabled'); } } if (!CBgroupID) { return; } if ($('input[type="checkbox"].' + CBgroupID + ':not(:checked)').length) { $('input[type="checkbox"]#' + CBgroupID).removeAttr('checked'); } else { $('input[type="checkbox"]#' + CBgroupID).attr('checked', 'checked'); } if ($('input[type="checkbox"].' + CBgroupID+':checked').length) { $('input[type="button"][class*="' + CBgroupID + '"]').removeAttr('disabled'); } else { $('input[type="button"][class*="' + CBgroupID + '"]').attr('disabled', 'disabled'); } if ($('input[type="checkbox"].' + CBgroupID + ':checked').length === 1) { $('.jToEdit').removeAttr('disabled'); } else { $('.jToEdit').attr('disabled', 'disabled'); } delete CBgroupID; });

Группа 1

Общий


Группа 2

Общий



Пример в fiddle


Ответ

$(document).on('change', 'input[type=checkbox]', function () { var $this = $(this), $chks = $(document.getElementsByName(this.name)), $all = $chks.filter(".chk-all"); if ($this.hasClass('chk-all')) { $chks.prop('checked', $this.prop('checked')); } else switch ($chks.filter(":checked").length) { case +$all.prop('checked'): $all.prop('checked', false).prop('indeterminate', false); break; case $chks.length - !!$this.prop('checked'): $all.prop('checked', true).prop('indeterminate', false); break; default: $all.prop('indeterminate', true); } });


В цикле while на c# не запускается Console.WriteLine

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace CyclesDoWhile { class Program { static void Main(string[] args) { //Количество конфет в пачке int candies = 200;
//Съедено конфет int candiesEaten = 0;
while(candiesEaten != 0) { candies--; candiesEaten++; Console.WriteLine("Конфет съедено. Осталось: " + candies + " Конфет съедено" + candiesEaten); }

Console.ReadKey(); } } }
Этот код работал. Запускался, как положено. Сегодня решил повторить этот урок, все стер. Написал заново. Запускает пустое консольное окно. В чем ошибка?


Ответ

У вас ошибка в условии цикла
//Количество конфет в пачке int candies = 200;
//Съедено конфет int candiesEaten = 0;
while(candiesEaten != 0) ^^^^^^^^^^^^
Данный цикл ни разу не выполнится.
Я думаю вы имеете в виду
//Количество конфет в пачке int candies = 200; //Съедено конфет int candiesEaten = 0;
while(candies != 0) ^^^^^^^

Чтение\Запись части байт из части файла

Имеем: обычный mp3 файл. Можно ли считать определенное количество байт, например 128 с конца файла, не читая весь поток байт? Можно ли перезаписать в конец файла эти 128 байт, не перезаписывая файл целиком? Можно ли удалить с конца файла 128 байт?
Если да, то как? Это нужно, т.к. хочу написать утилиту для редактирования ID3 тегов. И файлов будет очень много.
Я верно предположил, что если полностью читать-менять-записывать каждый файл, это будет занимать больше времени, чем менять куски данных в файлах?


Ответ

Если вы хотите теги редактировать, то я бы порекомендовал не писать велосипед, а использовать mp3agic, чтоб не мучиться с id3v2, id3v1 и т.п.

Можно ли спрятать JavaFX приложение в трей?

Эти 3 вопроса взаимосвязаны с вопросом о реализации одного проекта, но были распилены. Перед вами третий.
Второй, первый.
Есть GUI интерфейс который как запускается, так и выключается. И есть две операции, которые периодически выполняются. Причем одна маловесна, вторая до жути прожорлива.
Можно ли настроить окно JavaFX так, чтобы оно скрывалось в трей при нажатии крестика. (Не сворачивалось а именно в трей уходило)?


Ответ

Пример использования трея AWT + JavaFX:
https://gist.github.com/jewelsea/e231e89e8d36ef4e5d8a
import javafx.application.*; import javafx.geometry.Pos; import javafx.scene.*; import javafx.scene.control.Label; import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.stage.*;
import javax.imageio.ImageIO; import java.io.IOException; import java.net.URL; import java.text.*; import java.util.*;
// Java 8 code public class JavaFXTrayIconSample extends Application {
// one icon location is shared between the application tray icon and task bar icon. // you could also use multiple icons to allow for clean display of tray icons on hi-dpi devices. private static final String iconImageLoc = "http://icons.iconarchive.com/icons/scafer31000/bubble-circle-3/16/GameCenter-icon.png";
// application stage is stored so that it can be shown and hidden based on system tray icon operations. private Stage stage;
// a timer allowing the tray icon to provide a periodic notification event. private Timer notificationTimer = new Timer();
// format used to display the current time in a tray icon notification. private DateFormat timeFormat = SimpleDateFormat.getTimeInstance();
// sets up the javafx application. // a tray icon is setup for the icon, but the main stage remains invisible until the user // interacts with the tray icon. @Override public void start(final Stage stage) { // stores a reference to the stage. this.stage = stage;
// instructs the javafx system not to exit implicitly when the last application window is shut. Platform.setImplicitExit(false);
// sets up the tray icon (using awt code run on the swing thread). javax.swing.SwingUtilities.invokeLater(this::addAppToTray);
// out stage will be translucent, so give it a transparent style. stage.initStyle(StageStyle.TRANSPARENT);
// create the layout for the javafx stage. StackPane layout = new StackPane(createContent()); layout.setStyle( "-fx-background-color: rgba(255, 255, 255, 0.5);" ); layout.setPrefSize(300, 200);
// this dummy app just hides itself when the app screen is clicked. // a real app might have some interactive UI and a separate icon which hides the app window. layout.setOnMouseClicked(event -> stage.hide());
// a scene with a transparent fill is necessary to implement the translucent app window. Scene scene = new Scene(layout); scene.setFill(Color.TRANSPARENT);
stage.setScene(scene); }
/** * For this dummy app, the (JavaFX scenegraph) content, just says "hello, world". * A real app, might load an FXML or something like that. * * @return the main window application content. */ private Node createContent() { Label hello = new Label("hello, world"); hello.setStyle("-fx-font-size: 40px; -fx-text-fill: forestgreen;"); Label instructions = new Label("(click to hide)"); instructions.setStyle("-fx-font-size: 12px; -fx-text-fill: orange;");
VBox content = new VBox(10, hello, instructions); content.setAlignment(Pos.CENTER);
return content; }
/** * Sets up a system tray icon for the application. */ private void addAppToTray() { try { // ensure awt toolkit is initialized. java.awt.Toolkit.getDefaultToolkit();
// app requires system tray support, just exit if there is no support. if (!java.awt.SystemTray.isSupported()) { System.out.println("No system tray support, application exiting."); Platform.exit(); }
// set up a system tray icon. java.awt.SystemTray tray = java.awt.SystemTray.getSystemTray(); URL imageLoc = new URL( iconImageLoc ); java.awt.Image image = ImageIO.read(imageLoc); java.awt.TrayIcon trayIcon = new java.awt.TrayIcon(image);
// if the user double-clicks on the tray icon, show the main app stage. trayIcon.addActionListener(event -> Platform.runLater(this::showStage));
// if the user selects the default menu item (which includes the app name), // show the main app stage. java.awt.MenuItem openItem = new java.awt.MenuItem("hello, world"); openItem.addActionListener(event -> Platform.runLater(this::showStage));
// the convention for tray icons seems to be to set the default icon for opening // the application stage in a bold font. java.awt.Font defaultFont = java.awt.Font.decode(null); java.awt.Font boldFont = defaultFont.deriveFont(java.awt.Font.BOLD); openItem.setFont(boldFont);
// to really exit the application, the user must go to the system tray icon // and select the exit option, this will shutdown JavaFX and remove the // tray icon (removing the tray icon will also shut down AWT). java.awt.MenuItem exitItem = new java.awt.MenuItem("Exit"); exitItem.addActionListener(event -> { notificationTimer.cancel(); Platform.exit(); tray.remove(trayIcon); });
// setup the popup menu for the application. final java.awt.PopupMenu popup = new java.awt.PopupMenu(); popup.add(openItem); popup.addSeparator(); popup.add(exitItem); trayIcon.setPopupMenu(popup);
// create a timer which periodically displays a notification message. notificationTimer.schedule( new TimerTask() { @Override public void run() { javax.swing.SwingUtilities.invokeLater(() -> trayIcon.displayMessage( "hello", "The time is now " + timeFormat.format(new Date()), java.awt.TrayIcon.MessageType.INFO ) ); } }, 5_000, 60_000 );
// add the application tray icon to the system tray. tray.add(trayIcon); } catch (java.awt.AWTException | IOException e) { System.out.println("Unable to init system tray"); e.printStackTrace(); } }
/** * Shows the application stage and ensures that it is brought ot the front of all stages. */ private void showStage() { if (stage != null) { stage.show(); stage.toFront(); } }
public static void main(String[] args) throws IOException, java.awt.AWTException { // Just launches the JavaFX application. // Due to way the application is coded, the application will remain running // until the user selects the Exit menu option from the tray icon. launch(args); } }
Объяснение почему awt:
https://toster.ru/q/221896
1. Есть ль альтернатива AWT-шным средствам работы с треем в Java 8? Да. Через пень-колоду-нативные методы (обращающиеся к вызовам ОС). Как, я понял, копать нужно в сторону SWT и иже с ними. Да так что проще заюзать AWT (для моей задачи). 2. Можно ли средствами JavaFX 8 работать с треем не прибегая к AWT/SWING? Нет. JavaFX 8 не поддерживает работу с треем. Возможно, поддержка работы с треем будет добавлена в 9й версии.
Ссылка на stackoverflow.com по данному вопросу:
https://stackoverflow.com/questions/12571329/javafx-app-in-system-tray

Определить, находится ли точка в области

Есть ряд точек на плоскости и есть область (например круг). Нужно определить, какие точки входят в область.
Решение есть. Но оно подразумевает проверку каждой точки на вхождение в область. Натыкал я по рандому в редакторе 100000 точек. Нарисовал кружок. И вот я точно вижу, какие точки входят в область. Я даже не знаю про существование остальных, потому что область рисования огромна. А компьютер же будет перебирать все 100000 точек. А если их миллион? А миллиард? В итоге время вычисления прямо пропорционально количеству точек, тогда как человек с его тормознутостью даст ответ сразу. :)
Вот и подумалось мне, а как бы облегчить задачу программе? На ИИ я не претендую, но разобравшись в вопросе, можно топорно научить компьютер решать такую задачу. Нужно только понять, как это делает человек. На что обращает внимание. Какими величинами оперирует. Уж точно не координатами :)
Еще пример. Я выбираю точку и мне нужно найти ближайшую к ней. Не хочется перебирать все множество точек для этого.
UPD:
Есть вариант разбить всю область на подобласти с заданной детализацией. Каждую область хранить в памяти как отдельный объект и добавляя точки в основную область, добавлять их так же в подобласти (квадрат А2). Далее вычислять, какие подобласти пересекаются с поверяемой областью и проверять на вхождение в проверяемую область уже не всех точек, а лишь тех, которые содержатся в подобластях. В этом случае скорость поиска будет быстрее лишь в тех случаях, когда количество точек значительно выше количества областей. Количество областей зависит от детализации. Детализация будет зависеть от конкретной задачи (было бы не очень хорошо, если бы размер подобласти приближался к размеру проверяемой области).


Ответ

Несколько (не)очевидных моментов:
на картинке – все точки уже отсортированы самим своим расположением. Когда двигается «окно», осуществляется выборка узкого диапазона значений. В базе данных – длинный список безликих координат. на картинке точки имеют ненулевую площадь, т.е. можно говорить об округлении их координат до какой-то области.
Т.о. для быстрого решения, сравнимого со зрением нужно:
отсортировать координаты и построить индексы по X и Y, а может, и деревья для каждой точки - расстояния до соседних, или только список ближайших. На бумаге это делается в момент расстановки точек. округлять, или, вернее, «оквадрачивать» : ) – значения координат точек квантизировать до довольно крупной сетки. Форму окна - тоже - до угловатого подобия окружности, проходящего всегда между узлами координатной сетки.
Тогда задача приблизится по условиям к «естественному» зрению и станет заметно быстрее.

Если дельше приближаться к зрению, которое, в какой-то степени, нечёткое, для ч/б картинки задачу можно решить графически, не заморачиваясь распознаванием объектов. Допустим, белый фон и чёрные точки. Считаем, что примерно известны средняя площадь каждой черной точки и площадь окна. Размыть полностью картинку (Blur-Average в Photoshop). Получится оттенок серого. Из пропорции серый : черный = N_точек : (площадь фигуры : площадь точки) получаем примерное число точек.

В чем разница папок res/values и res/values-v11

Чем отличается файл styles.xml в папке values, от файла styles.xml в папке values-v11?
И что из них использует Android Studio?


Ответ

Android Studio использует ВСЕ потому, что это IDE - она собирает программу, а не выполняет ее.
А вот конкретное устройство, на котором запущено приложение, только те из ресурсов с квалификаторами (-v11 в вашем случае квалификатор версии SDK), которые подходят именно этому устройству. Вам нужно срочно ознакомиться с назначением квалификаторов при выборе альтернативных (наиболее подходящих под текущее устройство, на котором запущено приложение) ресурсов.
Конкретно по вашему вопросу. Файл стилей (и все прочие файлы в этой папке), который находится в папке /res/values-v11/ будет использоваться для устройств (смартфонов, планшетов и пр.) на которых установлено SDK11 или выше (Android 3.0 Honeycomb и новее). То, что находится в папке /res/values/ - ресурсы по умолчанию (без каких-либо квалификаторов), они будут использоваться для устройств, к которым не удалось выбрать ресурсы с квалификаторами. В вашем случае на всех устройствах с версией андроид меньше Android 3.0 Honeycomb (API 10 и менее).
Этот материал нужно усвоить очень серьезно, потому что это одна из основ андроид-разработки (правильная поддержка фрагментации устройств)

Что такое Android Support Repository?

Зачем нужен Android Support Repository? Что он делает и содержит?


Ответ

Android Support Repository - локальная копия на вашем компьютере репозитория Maven, которая содержит скомпилированные версии (.aar) библиотек поддержки Google (такие, как support:appcompat, support:design , support:v7 и тд.)
Находится по пути: \Android\Sdk\extras\android\m2repository\com\android\support
Используется для оффлайн работы IDE и ускорения сборки проекта, так как в этом случае не требуется выкачивать эти библиотеки из интернета, когда они понадобятся в проекте, она получает их с вашего компьютера.
Если вы не используете никаких библиотек поддержки Google, то локальная копия репозитория вам ни к чему, однако в современной андроид-разработке трудно представить приложение, которое не использует этих библиотек.
Android Support Library -локальная копия исходных кодов библиотек поддержки Google. Используется для того, чтобы, собственно, посмотреть, как там все устроено, скопировать ресурсы для кастомизации, сделать кастомные вью на основе виджетов библиотек поддержки и тп.

С чего начать большой веб-проект?

Тематика e-commerce. Проект достаточно большой, но согласно методикам "гибкой разработки", надо разбить проект на спринты в 1-2 недели каждый.
Каждый спринт должен заканчиваться вполне рабочей версией продукта, пусть и с очень ограниченным функционалом. После каждого спринта этот функционал будет становиться шире. Вроде бы все понятно.
Но что-то я застопорился с началом. Как начинаю расписывать задачу для спринта по функционалу, так сразу понимаю, что двумя неделями тут даже и не пахнет. Минимум месяц, а то и два!
Как обычно поступают в студиях, работающих по такой методике? Быть может накидать интерфейс на "бумажке" и начать с этого(с front-end)? Или с головой окунуться в самое сложное из функционала - и реализовывать это? Или сразу сесть и начать продумывать структуру БД? (но есть опасность, что что-нибудь важно упущу, а потом всю структуру переделывать заного). Как же выстроить канбан?


Ответ

Основная суть скрама - максимизировать обратную связь, не слишком отвлекая при этом разработчиков. Ради этого вводят итерации. Суть итерации - получение инкремента - пригодного к использованию приращения продукта. Пригодность к использованию (готовность) - это основной критерий. Потому что только то, что можно использовать, может дать настоящую, качественную обратную связь.
Прототип - дает обратную связь. Схема базы - вообще никак.
Учтите, что скрам - это методология для команд от 5 до 9 человек. Целиком он вам он не нужен.
Для команд из одного человека готовых методологий нет. Делайте в том порядке, в котором вам удобнее.
Единственное, что я бы вам посоветовал (раз совсем не знаете, за что схватиться) - начинать не с интерфейса или базы. А с расписывания основных user story. Выберите из них самые важные, и реализуйте одну за одной (дописывая по необходимости тесты, базу и код).

Как скрыть флаги при компиляции?

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


Ответ

Какой бы не был makefile, но там в конечном счете должен быть вызов компилятора. Если перед этой сторокой добавить @, то эта строка не будет выводиться. Теперь перед этой строкой достаточно вставить @echo gcc $@ или что то подобное и будет "красивый вывод". Аналогично и с линковкой.

четверг, 27 декабря 2018 г.

Слушатель выделения для ListView

Скажите, есть ли слушатель выделения элемента у ListView? Искал в гугле (на русском), но нашел только onClickListener'ы и тому подобные. Они реагируют на нажатие (когда палец отпустили), а мне нужно, чтобы слушатель реагировал на начало прикосновения к пункту списка, а потом на его отпускание. Есть такой слушатель предназначенный именно для ListView (а не onTouch)?


Ответ

Полагаю, что ваше решение - onTouchListener. Может и момент нажатия поймать, и момент отпускания.
OnTouchListener listener = new OnTouchListener() {
@Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //something break; case MotionEvent.ACTION_UP: //something } return true; } };
view.setOnTouchListener(listener);

Доступ к getAssets () из другого статического класса

Он работает с моей основной Activity и моим фрагментом, но если я использую метод LoadSound() в Sound классе, то getAssets() не работает.
public class CarnivoreFragment extends Fragment {
private int mCowSound; private View view;
private ImageButton mCowImageButton;
public CarnivoreFragment() { }
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_carnivore, container, false);
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Sound.createOldSoundPool(); } else { Sound.createNewSoundPool(); }
mCowSound = Sound.loadSound("cow.wav");
mCowImageButton = (ImageButton) view.findViewById(R.id.imageButtonCow); mCowImageButton.setOnClickListener(onClickListener);
return view; }
View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.imageButtonCow: Sound.playSound(mCowSound); Toast.makeText(view.getContext(), "Cow", Toast.LENGTH_SHORT).show();
break;
} } }; }
И мой класс "Sound":

public class Sound {
private static SoundPool mSoundPool; private static AssetManager mAssetManager; private static int mStreamID; private static Context context;
public Sound(Context context) { this.context = context; }
@TargetApi(Build.VERSION_CODES.LOLLIPOP) public static void createNewSoundPool() { AudioAttributes attributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_GAME) .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .build(); mSoundPool = new SoundPool.Builder() .setAudioAttributes(attributes) .build(); }
@SuppressWarnings("deprecation") public static void createOldSoundPool() { mSoundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0); }
public static int playSound(int sound) { if (sound > 0) { mStreamID = mSoundPool.play(sound, 1, 1, 1, 0, 1); } return mStreamID; }
public static int loadSound(String fileName) { mAssetManager = context.getAssets(); AssetFileDescriptor afd; try { afd = mAssetManager.openFd(fileName); } catch (IOException e) { e.printStackTrace(); Toast.makeText(context, "Не могу загрузить файл " + fileName, Toast.LENGTH_SHORT).show(); return -1; } return mSoundPool.load(afd, 1); }
}
Как решить эту проблему?


Ответ

Если создание экземпляров класса не входит в алгоритм использования класса Sound (так как все поля и методы в нем статические), то ваши методы не смогут получать контекст (так как конструктор не отрабатывает), который необходим для работы метода getAssets() В качестве решения можно предложить передавать контекст через параметры метода, в котором он требуется:
public static int loadSound(Context context, String fileName) { mAssetManager = context.getAssets(); .... }
Вызов из фрагмента:
mCowSound = Sound.loadSound(getActivity(), "cow.wav");
Если экземпляра активити будет недостаточно для контекста getAssets(), то нужно использовать другие способы доступа к контексту. Более правильно - получить экземпляр контекста один раз при создании фрагмента и "подсовывать" его везде, где требуется, а не вызывать каждый раз метод его получения.

Перевод строки в десятичное число. Java

Есть такие строки:
0x16 012 0b10 62
Нужно перевести их в:
22 10 2 62
соответственно, но при использовании Integer.parseInt(String, int) получаю NumberFormatException, как решить эту проблему?


Ответ

например, можно написать такую функцию
private static int StringToInteger(String input) { if(input.startsWith("0x")) { return Integer.parseInt(input.substring(2), 16); } else if(input.startsWith("0b")) { return Integer.parseInt(input.substring(2), 2); } else if(input.startsWith("0") && input.length() > 1) { return Integer.parseInt(input.substring(1), 8); } else { return Integer.parseInt(input); } }

Как стилизовать элемент счетчика?

  • 24

  • Как можно получить такой элемент как на картинке с помощью css (белая полоска зачеркивания идет перед цифрой)?
    P.S.: цифры при этом меняются динамически


    Ответ

    span { display: inline-block; background: #ffd800; font: 20px/1 Arial; width: 20px; border-radius: 5px; } span:before { content: ''; display: block; position: relative; top: 11px; left: 0; width: 20px; height: 2px; background: #fff; } 24

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

    Кастинг в коде это нормальное явление или повод задуматься над тем что, что то с кодом не так?


    Ответ

    Кастинг, кастингу рознь. К примеру, если у вас в коде есть static_cast, то это может быть подозрительно, но вряд-ли опасно. Тем не менее, даже со static_cast нужно убедиться, что это не просто безответственная попытка «заткнуть» компилятор, а явное и нужное преобразование. Как правило, такие вещи нужны на стыке кода библиотек, но, в идеальном случае лучше избегать и static_cast
    Если у вас в коде появляется dynamic_cast, то есть вероятность, что вы неправильно используете полиморфизм. Тем не менее, с точки зрения корректности программы, dynamic_cast не является проблемой. Он не может ничего такого добавить, чтобы сделало программу некорректной(т.е. он не служит «затычкой» компилятора). Поэтому наличие dynamic_cast может служить признаком неправильного дизайна(и пессимизации), но не более того.
    Если у вас в коде есть const_cast, то наиболее вероятно, что у вас в коде имеет место ошибка дизайна, которая должна быть исправлена как можно скорее. В противном случае вы сами знаете, что делаете и const_cast там не случаен. Прибегать к нему стоит лишь в том случае, когда других вариантов уже не осталось. И даже в этом случае стоит 100 раз всё обдумать и взвесить, т.к. const_cast не снимает константность с объектов, которые были рождены таковыми изначально. Точнее он может снять, а может и не снять — UB, если не ошибаюсь будет в этом случае.
    Наконец, если у вас в коде есть reinterpret_cast и он не находится в коде, который работает на стыке кроссплатформенного модуля и модуля специфичного конкретной ОС, то у вас с большой долей вероятности есть проблема.
    Если же у вас в коде есть C-style касты, то, сначала, замените их на C++ аналоги, а потом удалите те, что не являются необходимостью.
    В целом, любой оператор явного преобразования является потенциальной проблемой, поэтому их использование желательно свести к минимуму. Каждое такое использование должно иметь смысл и быть необходимым.

    Как правильно обработать порядок арифметических операций?

    Делаю что-то вроде обработчика выражений, как в Excel...
    Есть входящая строка String inputStr = "5+5-10/8+8*2" (любые числа и действия).
    Как реализовать приоритет действий? Нужен алгоритм.


    Ответ

    Эта задача решается с использованием стека через формирование и подсчёт Обратной Польской Нотации .

    Как из String сделать &str (возникает ошибка времени жизни ссылки)

    Написал функцию:
    fn read_str<'a>() -> &'a str { let mut input = String::new(); io::stdin().read_line(&mut input).ok(); let output : &str = &input[..]; &output }
    При компиляции возникает ошибка
    src/main.rs:13:26: 13:31 error: `input` does not live long enough src/main.rs:13 let output : &str = &input[..]; ^~~~~ src/main.rs:10:30: 15:2 note: reference must be valid for the lifetime 'a as defined on the block at 10:29... src/main.rs:10 fn read_str<'a>() -> &'a str { src/main.rs:11 let mut input = String::new(); src/main.rs:12 io::stdin().read_line(&mut input).ok(); src/main.rs:13 let output : &str = &input[..]; src/main.rs:14 &output src/main.rs:15 } src/main.rs:11:32: 15:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 11:31 src/main.rs:11 let mut input = String::new(); src/main.rs:12 io::stdin().read_line(&mut input).ok(); src/main.rs:13 let output : &str = &input[..]; src/main.rs:14 &output src/main.rs:15 }
    Пробовал брать строку io::stdin().read_line(&mut input).ok(); в фигурные скобки, дабы ограничить &mut, но это не помогает.


    Ответ

    Вернуть из функции можно только ссылку на статический объект (с временем жизни 'static) или ссылку, которую вы получили во входных параметрах.
    Вы пытаетесь вернуть ссылку на объект созданный в стеке функции. После завершения функции все объекты в стеке будут уничтожены. Rust не позволит создать ссылку на объект, который она может пережить. Использование после освобождения (use after free)
    В вашем случае лучше всего вернуть String. Накладные расходы в этом случае невелики, так как почти вся информация внутри строки хранится в куче.

    Большинство проблем начинающих писать на Rust связаны с непониманием назначения различных типов указателей. Если не вдаваться в подробности, их там можно насчитать пять штук.
    Ссылки в Rust используются для передачи данных без передачи права владения. Например если у вас есть структура, в которой хранится строка:
    struct Person{ name:String }
    то выдавать информацию о ее содержимом лучше так:
    impl Person{ pub fn get_name(&self)->&str{ &self.name } }
    или можно вернуть копию строки:
    pub fn get_name_clone(&self)->String{ self.name.clone() }
    Но это приведет к дополнительным расходам на копирование строки. Расходы здесь возникают именно из-за копирования - вызова метода clone(), который создает вторую копию данных строки в куче, а не из-за того, что функция возвращает строку.
    Можно вернуть строку из структуры без копирования:
    pub fn get_name_own(self)->String{ self.name }
    Но после вызова этого метода исходный объект Person перестанет существовать, так как право владения было передано.
    Еще одна распространенная причина проблем - попытка хранить ссылки на другие объекты в структуре. Ссылки накладывают кучу ограничений на время жизни и мутабельность связанных объектов. Прежде чем это делать, стоит дважды подумать о возможности использования других типов указателей.

    Синхронизация выполнения функций

    Синхронизация в javascript. Например, есть три функции:
    func1(function(){}); // асинхронная с callback func2(function(){}); // асинхронная с callback func3(); // синхронная возвращает true-false
    Нужно, чтобы после того, как func1 и func2 вызвали свои callback, а func3 вернул true, вызвать функцию func4
    Как правильно и лучше всего это сделать, если ли стандартная техника для такого?


    Ответ

    Вариант 1 - наиболее разумный - использовать Promise и Deferred
    http://api.jquery.com/promise/
    http://api.jquery.com/jQuery.when/
    http://api.jquery.com/deferred.promise/
    Код:
    var d1 = $.Deferred(); var d2 = $.Deferred(); var d3 = $.Deferred();
    func1(function() { d1.notify(); }); func2(function() { d2.notify(); }); func3(); d3.notify();
    $.when( d1, d2, d3 ).done(function () { // Выполнить результирующее действие. });
    Вариант 2 - завести счетчик количества выполняемых функций (не требует библиотек) и отслеживать выполнение в общем callback-е. Возможно также вместо счетчика использовать массив с именами функций.
    var currentCallbacks = 0; var expectedCallbacks = 3;
    var commonCallback = function() { currentCallbacks++; if (currentCallbacks == expectedCallbacks) { // Выполнить результирующее действие. } };
    func1(function(){commonCallback();}); func2(function(){commonCallback();}); func3(); commonCallback();
    Вариант 3 - _underscore.js имеет функцию after. Если библиотека уже подключена, можно использовать её функционал.
    Вернёт копию функции function, модифицированную таким образом, что она будет запущена только после того, как будет вызвана count раз. Удобно использовать при работе с асинхронными запросами, например, чтобы убедиться, что все обращения к серверу завершились.
    var commonCallback = _.after(3, function() { // Выполнить результирующее действие... });
    func1(function() { commonCallback(); }); func2(function() { commonCallback(); }); func3(); // Внутри должен перед выходом из функции вызываться commonCallback();
    var functions = [func1, func2, func3]; var runProcess = function() { _.each(functions, function(func) { func(); }); };
    runProcess();
    Вариант 4 - построить цепочку вызовов, но убивает все плюсы параллелизма.
    func1(callback1);
    function callback1() { ... func2(callback2); }
    function callback2() { ... func3(); // Выполнить результирующее действие. }

    Генерация сочетаний без повторений

    Требуется перебрать все комбинации группы символов от A до X где X может быть любой другой буквой.
    Пример: дана последовательность ABCD, функция должна выдать AB, AC, AD, BC, BD, CD, ABC, BCD, CDA, ABD (вроде ничего не забыл), т.е. позиция символа в группе не важна - важна лишь уникальность самой группы.
    Гуглил в сторону размещений и сочетаний. Но так и не понял что именно из этого мне требуется. Грешен - не учил математику. Умные люди, объясните на пальцах или кодом, буду признателен.
    Update: Обычно говорят, - и года не прошло. А вот у меня как раз прошел. Снова понадобилось, в этот раз подошел обстоятельно - вот код на PHP:
    function gen_comb ($rest, $current = "", $container = []) { // Если пустой текущий и есть остаток if(!$current and $rest) { // Текущему даем первый символ остатка $current = substr($rest, 0, 1); // Потом для каждого в остатке for($i=strlen($rest); $i > 0; $i--) // формируем пару с текущим и записываем в вывод $container[] = $current . substr($rest, $i, strlen($rest)); // при этом проверяем - если в остатке один if(strlen($rest) == 1 and $current) // возвращаем результат return $container; // если в остатке больше одного и при вычете еще останется if(strlen($rest) - 1) // возвращаем рекурсивный результат с уменьшенным на 1 остатком return gen_comb(substr($rest, 1, strlen($rest)), "", $container); } }


    Ответ

    Предисловие
    Я очень люблю следующий алгоритм из-за его просто детской простоты. Он не претендует на звание самого быстрого алгоритма, но является самым простым для понимания из всех, что я встречал.
    Алгоритм
    Если учитывать и одиночные комбинации (A, B, C, D), то таких комбинаций всего 2n - 1, где n - количество символов в исходной строке.
    Допустим, что у нас строка из n символов. То есть, у нас n позиций в строке.
    A B C D E F G H ... n-1 n // ^ ^ ^ ^ ^ ^ ^ ^ ... ^ ^ 1 2 3 4 5 6 7 8 ... n-1 n // порядковый номер каждой позиции
    Рассмотрим каждую позицию нулём (0) либо единицей (1). Договоримся ставить 1 на той позиции, на которой мы хотим видеть символ, а 0 на той, на которой не хотим.
    Получится примерно следующая строка из n нулей и единиц
    0 1 0 0 1 0 0 0 ... 0 0 // полученная закодированная строка ^ ^ ^ ^ ^ ^ ^ ^ ... ^ ^ 1 2 3 4 5 6 7 8 ... n-1 n // порядковый номер каждой позиции
    Эта строка кодирует комбинацию
    _ B _ _ E _ _ _ ... _ _ // комбинация строка ^ ^ ^ ^ ^ ^ ^ ^ ... ^ ^ 1 2 3 4 5 6 7 8 ... n-1 n // порядковый номер каждой позиции
    А теперь выпишем двоичный набор длиной в n элементов
    0 0 0 0 0 0 0 0 ... 0 0|_ _ _ _ _ _ _ _ ... _ _ 0 0 0 0 0 0 0 0 ... 0 1|_ _ _ _ _ _ _ _ ... _ n 0 0 0 0 0 0 0 0 ... 1 0|_ _ _ _ _ _ _ _ ... n-1 _ 0 0 0 0 0 0 0 0 ... 1 1|_ _ _ _ _ _ _ _ ... n-1 n .......................|......................... 1 1 1 1 1 1 1 1 ... 1 0|A B C D E F G H ... n-1 _ 1 1 1 1 1 1 1 1 ... 1 1|A B C D E F G H ... n-1 n
    Этот набор выписывается достаточно просто. Если просто, то на каждой новой строке к последнему элементу прибавляется единица. И если в результате получается число больше единицы, то позиция обнуляется и единица добавляется на соседнюю слева позицию и т.д.
    Этот набор (без первого) будет описывать всевозможные комбинации исходной строки.
    Пример
    Возьмём строку ABCD. В ней 4 символа, а значит, у нас будет 24 - 1 = 15 комбинаций.
    Выпишем двоичный набор из 4 элементов
    0 0 0 0|_ _ _ _ 0 0 0 1|_ _ _ D 0 0 1 0|_ _ C _ 0 0 1 1|_ _ C D 0 1 0 0|_ B _ _ 0 1 0 1|_ B _ D 0 1 1 0|_ B C _ 0 1 1 1|_ B C D 1 0 0 0|A _ _ _ 1 0 0 1|A _ _ D 1 0 1 0|A _ C _ 1 0 1 1|A _ C D 1 1 0 0|A B _ _ 1 1 0 1|A B _ D 1 1 1 0|A B C _ 1 1 1 1|A B C D
    И получаем следующие варианты
    1) D 2) C 3) CD 4) B 5) BD 6) BC 7) BCD 8) A 9) AD 10) AC 11) ACD 12) AB 13) ABD 14) ABC 15) ABCD
    Если вам не нужны одиночные комбинации, то можете их выбросить :)

    вторник, 25 декабря 2018 г.

    Пиксельная линейка в chrome

    После переустановки Chrome пропала пиксельная линейка. Говорят, что ее как-то можно включить, если не врут, подскажите как. Спасибо.


    Ответ

    F12 → сочетание клавиш Ctrl+Shift+M F12 → вторая сверху слева кнопка панельки (Toggle Device Mode):


    Чтобы включить также показ линий, ограничивающих элемент на этой линейке нужно включить опцию "Show Rulers". Жмём F12 → F12 и ставим галку в пункте General → Elements → Show Rulers:


    Вот что получается:

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

    Нестандартный вывод текста в TextView

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


    Ответ

    Написал код onDraw(Canvas canvas) своего класса наследника TextViewрешающий задачу для меня. Комментарии описываю последовательность действий:
    @Override protected void onDraw(Canvas canvas) { // круг, в который вписан текст canvas.drawCircle(mRadius, mRadius, mRadius, mGlowPaint); // высота строки float textHeight = mTextPaint.getFontSpacing(); // измеряем длинну текста float widthText = mTextPaint.measureText(mText); if(widthText <= mRadius*2) { // всего одна строка помещается - рисуем ее и выходим canvas.drawText(mText, mRadius, mRadius, mTextPaint); return; } // 1 Делим строку на два, сдвигаем к ближайшему пробелу. получаем индекс пробела, близкого к середине текста int centerSpace = calcCenterSpace(mText); // 2 Сначала рисуем текст вверх : String leftString = mText.substring(0, centerSpace); int cnt = 0; // количество прорисованных строк вверх float widthLine; int n; while (true) { // измеряем длинну строки widthLine = calcWidthLine(mRadius, textHeight * cnt++); // считаем сколько символов поместится в новой строке n = mTextPaint.breakText(leftString, false, widthLine, null); if (n == 0) // прерываем, так как строка слишком длинная break; // создаем строку int rest = leftString.length() - n; // проверка на последнюю строку if (rest != 0) { String s = leftString.substring(leftString.length() - n); // обрезаем до первого пробела int fixed = s.indexOf(' '); // создаем новую аккуратную строку s = s.substring(fixed + 1); // рисуем ее на высоте соответствующую данной строке canvas.drawText(s, mRadius, mRadius - textHeight * cnt + textHeight, mTextPaint); // сокращаем левый кусок текста на длинну отрисованной строки leftString = leftString.substring(0, leftString.length() - s.length()); } else { // последняя строка canvas.drawText(leftString, mRadius, mRadius - textHeight * cnt + textHeight, mTextPaint); break; } } // 3. Теперь рисуем вниз String rightString = mText.substring(centerSpace); cnt = 0; // количество прорисованных строк вверх while(true){ widthLine = calcWidthLine(mRadius, textHeight * cnt++); n = mTextPaint.breakText(rightString, false, widthLine, null); if (n == 0) // прерываем если весь текст не поместился break; int rest = rightString.length() - n; if(rest != 0) { String s = rightString.substring(0, n); int fixed = s.lastIndexOf(' '); s = s.substring(0, fixed); canvas.drawText(s, mRadius, mRadius + textHeight * cnt, mTextPaint); rightString = rightString.substring(s.length(), rightString.length()); } else { canvas.drawText(rightString, mRadius, mRadius + textHeight * cnt, mTextPaint); break; } } }
    private static int calcWidthLine(float r, float b){ double a = Math.sqrt(r * r - b * b); return (int)(2*a); }
    private static int calcCenterSpace(String text){ int index = text.length()/2; if(text.charAt(index) == ' ') return index; String subLeft = text.substring(0, index); int indexSpaceLeft = subLeft.lastIndexOf(' '); String subRight = text.substring(index + 2); int indexSpaceRight = subRight.indexOf(' '); if(index - indexSpaceLeft <= indexSpaceRight) return indexSpaceLeft; else return indexSpaceRight; }
    Алгоритм не идеален, на поставленную задачу выполняет. Еще в планах сделать растягивание строки. Оптимизация и недочеты приветствую. Вот скриншоты:

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

    При уставновке фокуса в EditText, на экране появляется клавиатура. Как реализовать её блокировку (убрать всплывание)?


    Ответ

    Сам уже нашёл. Нужно установить свойство:
    editText.setInputType(InputType.TYPE_NULL);

    Програмно снять выделение с TreeView

    Необходимо снять выделение с TreeView при удалении элемента. По умолчанию выделяется первый элемент, а задать SelectedItem = null не получается так как это свойство только для чтения. Как это реализовать?


    Ответ

    В обычном случае вы не создаёте элементы TreeView вручную, а генерируете их автоматически, используя ItemsSource + ItemTemplate
    При этом treeView.SelectedItem будет не TreeViewItem, а элемент коллекции, привязанной к ItemsSource. Так что приведение к типу TreeViewItem не сработает.
    Чтобы получить из этого собственно визуальный элемент, обычно применяется конструкция list.ItemContainerGenerator.ContainerFromItem(selectedItem);. Но в случае TreeView она, к сожалению, работает лишь на верхнем уровне: каждый TreeViewItem рекурсивно сам является TreeView, и заботится сам о своих контейнерах, так что list.ItemContainerGenerator ничего не знает о вложенных частях дерева.
    Неплохое универсально работающее (но многословное) решение — следить за изменением выделенного элемента, и запоминать его в code behind.
    Пример:


    public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new[] { new DataHolder("Привет-привет", null), new DataHolder("Пока-пока", null), new DataHolder(null, new[] { new DataHolder("Я очень", null), new DataHolder("буду ждать", new[] { new DataHolder("звонка", null) }), }), };
    TreeViewItem selectedItemTV = null; TV.AddHandler(TreeViewItem.SelectedEvent, (RoutedEventHandler)((sender, args) => selectedItemTV = (TreeViewItem)args.OriginalSource));
    TreeViewItem selectedItemTV2 = null; TV2.AddHandler(TreeViewItem.SelectedEvent, (RoutedEventHandler)((sender, args) => selectedItemTV2 = (TreeViewItem)args.OriginalSource));
    var dt = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(5) }; dt.Tick += (sender, args) => { if (selectedItemTV != null) { selectedItemTV.IsSelected = false; selectedItemTV = null; } if (selectedItemTV2 != null) { selectedItemTV2.IsSelected = false; selectedItemTV2 = null; } }; dt.Start(); } }

    public class DataHolder { public string Key { get; private set; } public IEnumerable Value { get; private set; }
    public DataHolder(string key, IEnumerable value) { Key = key; Value = value; } }
    Ну или вы можете подписаться обычным способом в XAML'е: TreeViewItem.Selected="TVItemSelected"

    Ещё есть решение с полным рекурсивным обходном дерева, и поиском TreeViewItem'а, как описано здесь. Но оно мне кажется слишком уж неэффективным, и наверняка плохо дружит с виртуализацией.

    Postgresql Выборка по строке ФИО

    Есть строка фильтра. Пользователь вводит в нее часть имени или фамилии или отчества, отображается список частичных совпадений, пользователь вводит польностью фимилию Иванов, отображаются Ивановы, далее он ставит пробел и вводит С, поиск должен найти всех Ивановых, чьи имена или отчества начинаются на С.
    В список не должны попадать фамилии на С., в БД ФИО хранятся отдельными полями. Как привильнее всего построить текст запроса? Я разбивал строку на слова и для каждого слова я добавлял условия, получалось следующее:
    SELECT * FROM users WHERE (name ILIKE word1 OR surname ILIKE word1 OR patronymic ILIKE word1) AND (name ILIKE word2 OR surname ILIKE word2 OR patronymic ILIKE word2) AND (name ILIKE word3 OR surname ILIKE word3 OR patronymic ILIKE word3)


    Ответ

    А почему вы не хотите фамилии на С ? Если считать, что пользователь вводит сначала имя Иван, а потом вводит букву С было бы логично показать Ивана Сидорова, а Сидора Иванова наверное не надо. А если он вводит две буквы, то уже начинать искать ? как ему найти "Гевара Че" ?
    Предлагаю такую логику: пока слово одно - ищем его во всех трех полях по частичному совпадению. Но возможно надо ограничить минимальный размер слова, если оно из одной буквы, то боюсь результатов слишком много будет. Если слов более одного - то первое слово ищем во всех полях по точному совпадению, а остальные слова - то частичному совпадению.
    Запрос, реализующий вышеуказанную логику:
    select distinct users.* from ( select split_part(S,' ',N.column1) w1,split_part(S,' ',N.column2) w2, split_part(S,' ',N.column3) w3, substr('%%',2-N.column1/2) p1,substr('%%',2-N.column2/2) p2, substr('%%',2-N.column3/2) p3,(rtrim(S) like '% _')::int+1 np from (values(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,2,1),(3,1,2)) N, (select Cast('Пушкин А С' as varchar) S) S ) A join users on name LIKE w1||substr(p1,np,1) and surname LIKE w2||substr(p2,np,1) and patronymic LIKE w3||substr(p3,np,1)
    Единственный параметр передаваемый в запрос - ваша строка "Пушкин С А". Перед передачей строки из нее надо удалить лишние пробелы, т.е. слова должны быть разделены строго одним пробелом. Если нужен регистронезависимый поиск - приведите строку к нужному регистру в самом запросе
    По работе запроса: цифры в подзапросе N - весь набор расположения слов. w1-w3 - выделенные компоненты из строки, согласно номерам в N. p1-p3 - один % для первого слова строки, и %% для остальных. np - признак поиска полного соответствия (когда слов более 1). substr в самом низу по этому признаку берут или не берут % для like.