Страницы

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

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

Как изменить место сохранения сгенерированной модели через artisan?

Начал изучать Laravel.
Столкнулся с одной непоняткой: при создании модели таблицы (через artisan) она создается в app/, что не очень хорошо, учитывая, что этих таблиц может быть больше 40.
Как изменить место хранения моделей? Решения не нашел. Везде говориться: "Да, можно поменять место хранения моделей" и все. Ничего более.
Кто знает как это сделать - поделитесь знанием.
p.s. Если важно - проект в шторме, тип - composer project


Ответ

Создаёте директорию app/Models Модели создаёте с учётом п.1: php artisan make:model Models/MyModel Получаете свою MyModel в пространстве имён App\Models в app/Models/MyModel.php
Чтобы перенести User туда же, надо изменить namespace и там, где этот класс используется (например, в config/auth.php)

Выделение и копирование текста в виртуальном терминале

Как правильно осуществляется выделение, копирование и вставка текста в виртуальном терминале в Ubuntu?
пример:
#команда $ wpa_passphrase <имя_точки_доступа>
#вывод в терминале network={ ssid="test" psk="12345678" psk=fe727aa8b64ac9b3f54c72432da14faed933ea511ecab1 5bbc6c52e7522f709a }
Как правильно выделить, скопировать и вставить в следующие команды hex ключ?


Ответ

если имеется «мышь», то можно установить пакет gpm, и использовать её для копирования (надо выделить фрагмент текста с помощью левой кнопки) и вставки в командную строку (с помощью средней кнопки). собственно, как и при работе с эмулятором терминала, запущенным под управлением x-сервера

если «мыши» нет, то понадобится мультиплексор терминала
например, с помощью запущенной программы gnu/screen (пакет обычно называется screen) можно действовать так
перейти в режим копирования/листания с помощью любой из комбинаций: C-a [, C-a C-[, C-a (подразумевается, что вы не меняли умолчальный метасимвол a с помощью команды escape). переместить курсор с помощью клавиш h, j, k и l (т.н. vi-стиль управления курсором) в начало выделяемого фрагмента и отметить его с помощью пробела. переместить курсор в конец выделяемого фрагмента и отметить его повторным нажатием пробела. screen вернётся в «нормальный» режим работы. вставить ранее выделенный фрагмент в текущую позицию с помощью любой из комбинаций: C-a ], C-a C-]

Как правильно занимать и отпускать Mutex?

Нужно, с одной стороны, обеспечить запуск единственного экземпляра приложения, с другой - в тестах надо имитировать запуск и выключение приложения.
Пишу соответствующие методы:
public static class Client { private static Mutex mutex;
public static void Start() { var isSingle = false; mutex = new Mutex(false, guid, out isSingle); if (!isSingle) { Log.Add("Программа уже запущена."); Environment.Exit(1); } }
public static void Close() { if (mutex != null && !mutex.SafeWaitHandle.IsClosed) { Log.Add("Wait mutex..."); mutex.WaitOne(); mutex.ReleaseMutex(); mutex.Close(); } } }
Если создание и проверка в целом выглядят понятно, то вот с закрытием явные проблемы. По синтаксису хотелось вызвать просто ReleaseMutex, ему потребовался WaitOne, а потом оказалось, что ReleaseMutex не закрывает хендл и при следущем тесте старт уже невозможен, для чего пришлось добавлять ещё и Close()
Вопрос - так и надо делать или есть варианты проще?


Ответ

Вы пытаетесь использовать сразу два разных свойства мьютекса:
Уникальность именнованного мьютекса в системе Возможность захватить его только одному клиенту одновременно
Первое свойство характерно не только для мьютексов, но для всех глобальных объектов синхронизации. Суть его в том, что в системе может существовать только один объект синхронизации с определенным именем.
Попытка создать такой же объект откроет уже существующий (созданный в другом процессе), но при этом явно вам на это укажет - возвратом параметраcreatedNew == false.
Мьютекс существует до тех пор, пока его хэндл не будет закрыт во всех процессах. Т.е. createdNew (ваш isSingle) будет выставлен в false в случае, если такой мьютекс уже где-то (в другом экземпляре приложения) существует.
Т.е. сам по себе механизм предотвращения повторного запуска опирается исключительно на свойство единственности существования именованного Mutex, а не на возможность эксклюзивно его захватить.
Методы WaitOne, ReleaseMutex и первый параметр конструктора - initiallyOwned используются для эксклюзивного захвата, и в вашем случае совершенно не нужны.
Минимальный код в вашем случае выглядит так:
public static class Client { private static Mutex mutex;
public static void Start() { var createdNew = false; mutex = new Mutex(false, "someid", out createdNew); if (!createdNew) { Console.WriteLine("Программа уже запущена."); Environment.Exit(1); } }
public static void Close() { if (mutex != null && !mutex.SafeWaitHandle.IsClosed) { Console.WriteLine("Close handle"); mutex.Close(); } } }
Чтобы проверить, что сам по себе факт того, что вы используете именно Mutex, не влияет на результат, можете попробовать заменить его на что-то другое, например семафор с максимальным лимитом в 100:
new Semaphore(0, 100, "someid", out createdNew)
В отличии от мьютекса, его могут захватить до 100 раз. Но, как и в случае мьютекса, сама возможность захвата не используется - и он точно так же будет предотвращать запуск второго экземпляра - за счет уникальности имени.

Bootstrap tooltip внутри компонента popover

Использую Bootstrap. Имеется форма. Я беру компонент tooltip и прикрепляю к инпутам, всё ок, все красиво, все работает без дописывания стилей.
Проблема в том, я хочу использовать компонент Tooltip внутри компонента Popover bootstrap (в popover у меня имеется форма, к инпутам подключаю tooltip). В данной ситуации tooltip слипаются в верхнем левом углу.
Пример - https://jsfiddle.net/martdn/pzmt4upb/4/


Ответ

Проблема была в том, что при использование компонента tooltip внутри компонента popover, приводило к некорректному позиционированию элементов подсказок. Из-за того, что не успевает посчитать позицию подсказок tooltip.
Решение - подсказки выводим после завершение загрузки навигации CSS. С помощью стандартного события Bootstrap shown.bs.popover
$('#popover').on('shown.bs.popover', function() { myTooltip(); });
Файлы с кодом на gist
//Tooltip content var myTooltip = function() { $('.has-error input').tooltip({ placement: 'left', title: function() { return $('#message').html(); } }).tooltip('show'); } //Popover jQuery(document).ready(function() { //Popover Content $("#popover").popover({ html: true, trigger: 'click', content: function() { return $('#popoverContent').html(); } }); //Show tooltip $('#popover').on('shown.bs.popover', function() { myTooltip(); }); //Remove tooltip when closing popover $('#popover').on('hide.bs.popover', function() { $('.tooltip').remove(); }); }); body { width: 800px; } .container { padding-top: 50px; width: 400px; }


Сортировка массива в java

Java. Прошу помощи. Необходимо массив из чисел int отсортировать в возрастающем порядке с помощью определенного способа - первым шагом сравнить и обменять элементы i и i+1, где i - четное число. Вторым шагом - где i - нечетное число. Повторять пока массив не будет отсортирован. Сделать надо с помощью дополнительного метода. Пример:
Как ни делал - выдает ошибку array out of bounds.
public static void firstMethod(int[] A) { int z, j; for (j=0; j

Ответ

То, что вы описали довольно сильно похоже на сортировку пузырьком, но несколько отличается (в сортировке пузырьком предполагается проход элементов подряд, следствием чего является получение за каждую итерацию максимального/минимального элемента из просматриваемых, здесь же несколько другая формулировка, а в итоге алгоритм совсем другой). P.S. Уточните, правильно ли вы поняли формулировку, если да, то реализация sort() вам подойдет, но если это, все-таки, пузырек, то воспользуейтесь методом bubbleSort()
public class Solution { public static void main(String[] args) { int[] massive = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
System.out.print("Начальное состояние массива: "); showout(massive);
sort(massive);
System.out.print("Состояние массива после сортировки: "); showout(massive); }
/** реализует ту сортировку, которую вы описали */ private static void sort(int[] massive) { boolean isAlreadySorted; do { isAlreadySorted = sort(massive, 0) & sort(massive, 1); } while (!isAlreadySorted); }
/** при необходимости меняет местами соседние элементы массива massive начиная с позиции startIndex и далее через одну */ private static boolean sort(int[] massive, int startIndex) { boolean isAlreadySorted = true; for (int index = startIndex; index < massive.length - 1; index += 2) { if (massive[index] > massive[index + 1]) { isAlreadySorted = false; swap(massive, index, index + 1); } } return isAlreadySorted; }
/** меняет местами элементы массива massive с индексами leftIndex и rightIndex */ private static void swap(int[] massive, int leftIndex, int rightIndex) { massive[leftIndex] ^= massive[rightIndex]; massive[rightIndex] ^= massive[leftIndex]; massive[leftIndex] ^= massive[rightIndex]; }
/** выводит элементы массива на экран */ private static void showout(int[] massive) { for (int index = 0; index < massive.length - 1; ++index) { System.out.print(massive[index] + ", "); } System.out.println(massive[massive.length - 1]); }
/** обычная сортировка пузырьком */ private static void bubbleSort(int[] massive) { boolean isAlreadySorted = false; for (int i = 0; i < massive.length - 1 && !isAlreadySorted; i++) { isAlreadySorted = true; for (int j = 0; j < massive.length - i - 1; j++) { if (massive[j] > massive[j + 1]) { swap(massive, j, j + 1); isAlreadySorted = false; } } } } }

Перегрузка методов с#

Чем вредна и полезна перегрузка методов в с#?


Ответ

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

Как назвать такой фрагмент кода?

private IMyType myProperty;
public IMyType MyProperty { get { if(myProperty==null) { myProperty = AppKernel.Get(); } return myProperty; } }
Как называется эта техника (создание экземпляра объекта в случае, если ссылка на объект пустая)? Является ли это каким-то паттерном? Во многих примерах вижу такой подход. Интересно, имеет ли он какое-то название?


Ответ

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

Docker растет директория

Столкнулся с проблемой, при каждой сборке проекта постоянно растет директория /var/lib/docker/vfs/dir/
Как можно ее почистить?
При этом docker volume ls ничего не выдает


Ответ

Спасибо за помощь! Вот решение:
docker rmi
image id можно узнать выполнив команду
docker images
Оказывается при сборке команда RUN добавляет новый слой к существующему образу, т.е. в Dockerfile встречается 2-е RUN команды, то образ будет с 2-я слоями и объемом равен первый слой + первый слой и незначительные изменения от 2-ой команды RUN https://xakep.ru/2015/06/04/docker-faq/ Раздел -- Почему, собирая образ с помощью Dockerfile, я получаю толстый слоеный пирог?

Скрипт для перезапуска неактивных процессов python

Есть скрипт, который может выполняться очень долгое время и если он станет неактивным (упадет, зависнет) нужно его перезапустить.
Какие программы, библиотеки, скрипты, модули смогут перезапускать неактивные процессы питона?
Запускать буду на windows и linux (Raspbian)


Ответ

Программы подобного вида называются watchdog (сторожевая собака). Но вот только отследить, что процесс упал - просто, то отследить, что процесс завис - сложно, а иногда никак нельзя. Скрипт может молотить локальный массив и просто грузить процессор, а может зависнуть в бесконечном цикле.
Как я делал подобное. Скрипт должен как то обновлять данные, что он работает. Например, писать в лог или обновлять дату файла. Вачдог запускается cron или чем то другим раз в минуту (пять минут, час) и проверяет этот файл. Если ничего не поменялось - нужно перезапускать.
В другом проекте я просто встроил в скрипт маленький http сервер, который просто отдавал статистику. вачдог скрипт делал curlом запрос и смотрел на результат. Также вачдог умел отправлять письма-отчеты и слал смс, если перезапуск не удавался.
Как по мне, то вачдог - это специфическая программа, которая пишется под каждую конкретную ситуацию. Но в современных системах они часто уже достаточно хорошо встроены. В линуксе тот же systemd умеет перезапускать сервисы, если они упали (но есть ли он на малинке - не знаю).
Также в линуксах можно использовать runit
В виндовсе если сделать сервис, то сама винда сможет перезапускать упавший сервис.
Некоторые админы пишут скрипты вачдога в таком виде:
вечный цикл: проверить, запущен ли скрипт если не запущен и счетчик перезапусков не превысил лимит, перезапустить спать 5 минут
Но у этого подхода есть один недостаток - этот скрипт также может упусть. Но его сильный плюс - его легко сделать кроссплатформенным.

сортировка массива пар (x, y) по y в Python

Я имею массив x и y, где y = f(x). Требуется отсортировать эти пары по y
Сейчас я это делаю так: завожу два list, делаю вручную сортировку по y, и хвостом при этом тяну x
Как это лучше сделать средствами языка? Или еще как?


Ответ

Можно использовать sort с сортировкой по ключу. Примерно так:
lst = [(1, 6), (2, 5), (3, 4), (8, 3), (7, 2)] lst.sort(key=lambda x: x[1]) print(lst)
Вывод:
[(7, 2), (8, 3), (3, 4), (2, 5), (1, 6)]

Как просмотреть __doc__ атрибута?

>>> class C(object): def __init__(self, value): self._x = value def _getx(self): return self._x def _setx(self, value): self._x = value def _delx(self): del self._x x = property(_getx, _setx, _delx, doc="I'm the 'x' property.")
>>> obj = C(123) >>> obj.x 123 >>> obj.x.__doc__ "int(x=0) -> integer
int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments
are given. If x is a number, return x.__int__(). For floating point
numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string,
bytes, or bytearray instance representing an integer literal in the
given base. The literal can be preceded by '+' or '-' and be surrounded
by whitespace. The base defaults to 10. Valid bases are 0 and 2-36.
Base 0 means to interpret the base from the string as an integer literal.
>>> int('0b100', base=0)
4" >>>
Как увидеть "I'm the 'x' property."", а не docstring для int?


Ответ

Попробуйте:
C.x.__doc__ или type(obj).x.__doc__

Поворот блоков по оси Y при наведении

Есть два блока, наложенных друг на друга. один повернут на 90 град по оси Y то есть нам не виден, а другой повернут на 0 град, нужно чтобы при наведении, первый блок поворачивался на -90 град, то есть его поворот по оси Y становился 0, и второй блок так же разворачивался на -90, то есть его поворот по оси Y составлял -90 град, не пойму что не так но крутятся они оба друг против друга .first { display: block; position: relative; width: 120px; height: 100px; background: #C7FFA8; text-align: center; padding: 15px; } .second { display: block; position: absolute; width: 120px; height: 100px; background: #FCFFA8; text-align: center; padding: 15px; top: 0; } .folder .second { transform: rotateY(90deg); } .folder .second, .folder .first { transition: 1s; } .folder:hover .second { transform: rotateY(0deg); transition-delay: 0.5s; } .folder:hover .first { transform: rotateY(-90deg); } .folder { display: block; position: relative; width: 120px; transition: 1s; }

Я стою лицом
А я повернут

Как видно, желтый блок выезжает по часовой, а зеленый прячется против часовой, хотя должен делать это тоже по часовой, чтобы создавался эффект как будто поворачивается карточка


Ответ

figure.container { border: 3px solid hsla(16, 71%, 30%, 1); width: calc(20rem); min-height: calc(30rem); position: relative; margin: 0 auto; background: radial-gradient(ellipse at center, hsla(212, 67%, 36%, 0) 0%, hsla(212, 67%, 36%, 0.65) 15%, hsla(211, 67%, 39%, 1) 23%, hsla(207, 69%, 51%, 1) 58%, hsla(212, 67%, 37%, 1) 79%, hsla(212, 67%, 36%, 0.9) 81%, hsla(212, 67%, 36%, .6) 83%, hsla(212, 67%, 36%, .8) 100%); box-sizing: border-box; } div.film { border: 1px solid hsla(0, 0%, 80%, 1); position: absolute; width: calc(100%); height: calc(100%); text-shadow: 0px 0px 1px hsla(0, 0%, 0%, .4); text-align: center; perspective: 1000px; transform-style: preserve-3d; transition: 2s; } figure.container:hover div.film { transform: rotateY(-180deg); } div.face { position: absolute; backface-visibility: hidden; width: calc(100%); min-height: calc(100%); background-image: linear-gradient(to top, hsla(16, 71%, 10%, 1) 0%, hsla(16, 71%, 8%, 1) 100%); } div.back { transform: rotateY(-180deg); background-image: linear-gradient(to top, hsla(16, 71%, 10%, 1) 0%, hsla(16, 71%, 8%, 1) 100%); } figure.container div.front, figure.container div.back { font: normal 2rem/4.4 arial, sans-serif; letter-spacing: .1rem; color: hsla(0, 0%, 100%, 1); }

Вход
Выход

Разложение подынтегральной функции с помощью формулы Эйлера

Решение интеграла в преобразовании Фурье
Численным методам этот интеграл не решить из за наличия комплексной мнимой единицы,порекомендовали Формула Эйлера с разложением подынтегральной функции на косинус и синус
Вопрос возник с применением Формулы Эйлера
Получается нужно вручную разделить формулу на 2 части присвоить согласно формуле Эйлера каждую часть к интегралу. Или существует другой вариант?
public void frmEiler(int U,int T) { double x1=0,x2=0; ///U*Math.Exp(-j * w * t) dt///формула double j = Math.Sqrt(-1);// мнимая единица double f = 0,w = 0; int t = 1; f = 1 / T; w = 2 * Math.PI * f; Math.Exp(-j * w * t) =U* Math.Cos(w * t) + j * Math.Sin(t); x1=Math.Cos(w * t); x2=j * Math.Sin(t); }
public double func1(double x1) { ///1-ая часть подыинтегральной функции return; }
public double func2(double x2) { ///2-ая часть подыинтегральной функции return; }


Ответ

Скорее всего с помощью формулы Эйлера Вы решили избавиться от мнимой единицы, чтобы вычислить численно интегралы. Я в математике не силен, не знаю верно ли, но решил попробовать.
Получается нужно вручную разделить формулу на 2 части присвоить согласно формуле Эйлера каждую часть к интегралу
По формуле Эйлера нужно вычислить интеграл sin'а и интеграл cos'а. Дальше из полученных результатов получить комплексное число.
Что я делал
Я создал класс NumericalIntegration, который интегрирует функцию с помощью Численного интегрирования. Т.к. существует несколько методов решения (я буду называть их способы, чтобы не путать с термином метод в программировании), поэтому я решил создать интерфейс, который будет подразумевать какой-то способ решения. А реализация этого интерфейса уже будет конкретным способом решения. Я так сделал, чтобы при разработки можно было добавить еще какие-то способы решения.
interface NumericalIntegrationRule { double Calculate(Func func, double min, double max, double subintervalsCount); }
У способа решения должен быть метод, который принимает функцию func, отрезок интегрирования [min,max] и число подинтервалов n, т.е. насколько частей делим отрезок, чем больше отрезков, тем больше точность интегрирования. Конечно же, лучше было бы сделать погрешность, но я по-быстрому заложился на количество отрезков. Можете сами потом изменить это.
А в классе интегрирования NumericalIntegration уже будет вызов нужного способа решения. Нужный способ передается через конструктор. Плюс добавил параметры по умолчанию: число отрезков.
class NumericalIntegration { public readonly NumericalIntegrationRule DefaultRule = null; public readonly int DefaultSubintervalsCount = 100000;
public NumericalIntegration() { DefaultRule = new TrapezoidalRule(); }
public NumericalIntegration(NumericalIntegrationRule defaultRule) { DefaultRule = defaultRule; }
public NumericalIntegration(NumericalIntegrationRule defaultRule, int defaultSubintervalsCount) : this(defaultRule) { DefaultSubintervalsCount = defaultSubintervalsCount; }
public double Calculate(NumericalIntegrationRule rule, Func func, double min, double max, double subintervalsCount) { return rule.Calculate(func, min, max, subintervalsCount); }
public double Calculate(Func func, double min, double max) { return Calculate(DefaultRule, func, min, max, DefaultSubintervalsCount); } }
Я реализовал только метод трапеций:
class TrapezoidalRule : NumericalIntegrationRule { public double Calculate(Func func, double min, double max, double subintervalsCount) { double result = 0; double step = (max - min) / subintervalsCount;
for (double i = min; i < max; i += step) result += ((func(i) + func(i + step)) / 2) * step;
return result; } }
А можно было бы на каждый способ решения в классе NumericalIntegration создать отдельный метод этого CalculateWithTrapezoidalRule, CalculateWithRectangleRule и т.д.
Теперь у нас есть классы для численного интегрирования. Можно их использовать для нахождения спектральной плотности. Я не в курсе как у Вас устроена система, поэтому я работал в консольном приложении и в этом приложении вынес расчет плотности в отдельный статический метод:
static Complex GetSpectralDensity(double amplitude, double frequency, double time) { NumericalIntegration integration = new NumericalIntegration(); double real = amplitude * integration.Calculate(x => Math.Cos(-frequency * x), 0, time); double imaginary = amplitude * integration.Calculate(x => Math.Sin(-frequency * x), 0, time); return new Complex(real, imaginary); }
Все как в формуле Эйлера: интегрируются обе части, а потом на основе их результатов создается комплексное число, которое и будет равно значения плотности.
Дальше, решил проверить результаты моей программы с результатами Mathcad. Mathcad, вроде бы, говорит, что результаты, вычисленные после преобразования по формуле Эйлера, будут такие же, как и результаты, полученные без преобразования. Проверил на этих же данных и свою программу.
static void Main(string[] args) { double amplitude = 25; double time = 50;
for (int frequency = -100, counter = 0; frequency <= 100; frequency++, counter++) Console.WriteLine("{0}: {1}", counter, GetSpectralDensity(amplitude, frequency, time).ToString()); }

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

Почему DataGrid такой медленный, или как придать приличный вид GridView?

Пишу проект на WPF. На одном из View необходимо выводить клиенту довольно большой по объему список объектов в виде таблицы. Идеально для этого подошёл бы DataGrid. Я не очень-то люблю "изобретать велосипеды", поэтому нашёл множество уже готовых решений (те же контролы от Syncfusion). Я уж было очень сильно обрадовался, однако столкнулся с серьёзной проблемой: привязывая коллекцию большого объёма (более сотни объектов) к DataGrid, процесс рендеринга самого контрола сильно затягивается (и это при том, что, унаследовавшись ObservableCollection, я добавил метод AddRange(), чтобы при добавлении каждого объекта не вызывалось событие интерфейса INotifyPropertyChanged). Если добавлять 200-300 объектов в коллекцию за раз и привязать их к DataGrid, процесс затянется уж очень надолго и приложение может вовсе зависнуть. Получение данных из базы и формирование модельных объектов происходят во вторичном потоке. Думал, что проблема в количестве объектов при их создании, однако, после использования профайлера, я понял, что все тормоза начинаются именно после вызова AddRange() на привязанной коллекции. Возможно, проблема в том, что каждый модельный объект реализует INPC? И содержит в себе ряд таких же вложенных объектов, также реализующих этот интерфейс? Как бы там ни было, я попробовал заменить DataGrid на GridView, и, в принципе, всё стало работать довольно быстро. Однако GridView не предоставляет множества преимуществ, которые имеются у DataGrid (начиная от элементарной сортировки и заканчивая готовым красивым оформлением). Теперь меня интересует, как придать более или менее приличный вид GridView. Например, как придать ему стиль "Metro"? Или же есть какая-то возможность, чтобы оптимизировать работу DataGrid? Ну не верится мне, что на рендеринг сотни модельных объектов уходит так много времени и это так затормаживает UI.
UPDATE:
ViewModel:
public class TaskEntitiesListViewModel : StoreUsingViewModel, IPageViewModel { #region fields private TaskEntityModel currentTask; private List cacheTaskEntityModelList; #endregion #region ctors public TaskEntitiesListViewModel() : base() { this.cacheTaskEntityModelList = new List(); this.TaskEntities = new ObservableCollectionExtended(); } #endregion #region INPCProperties public ObservableCollectionExtended TaskEntities { get; set; } #endregion #region eventSubscribers [EventSubscription("topic://Authorization/CorrectCredentialsEntered", typeof(OnUserInterface))] [EventSubscription("topic://Application/ViewUsual", typeof(OnUserInterface))] public async void InitTaskEntitiesListUsualAsync() { if (TaskEntities.Count != 0) TaskEntities.Clear();
var taskEntitiesListFromDAL = await Task.Factory.StartNew(() => Store.GetTaskEntityList(t => t.Owner, t => t.Creator, t => t.Base).ToList());
//wrapping each TaskEntity to TaskEntityModel if (cacheTaskEntityModelList.Count != 0) cacheTaskEntityModelList.Clear(); taskEntitiesListFromDAL.ForEach(t => cacheTaskEntityModelList.Add(new TaskEntityModel(t)));
TaskEntities.AddRange(cacheTaskEntityModelList.Where(t => t.IsOver == false).Take(100).ToList()); } #endregion #region IPageViewModel public string Name { get { return "TaskEntitiesList"; } } #endregion #region BaseViewModel public override void OnDataChangedGlobalEvent() { InitTaskEntitiesListUsualAsync(); } #endregion }
Код коллекции:
public class ObservableCollectionExtended : ObservableCollection { private bool _suppressNotification = false; protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { if (!_suppressNotification) base.OnCollectionChanged(e); }
public void AddRange(IEnumerable list) { if (list == null) throw new ArgumentNullException("list");
_suppressNotification = true;
foreach (T item in list) Add(item);
_suppressNotification = false; OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); }
public void ClearRange() { _suppressNotification = true;
ClearItems();
_suppressNotification = false; OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } }
Во вьюшке в качестве ItemsSource для DataGrid используется public ObservableCollectionExtended TaskEntities { get; set; }
UPDATE 2
код View:

UPDATE 3 Model:
public class TaskEntityModel : BaseModel { #region fields private string prop1; private string prop2; private string prop3; private string prop4; private string prop5; private DateTime dateProp1; private DateTime dateProp2; private DateTime dateProp3; private DateTime dateProp4; #endregion #region ctors public TaskEntityModel(TaskEntity taskEntity) : base(taskEntity) { //filling fields } #endregion #region INPCProperties
public string Prop1 { get { return prop1; } set { if (value != prop1) { prop1 = value; OnPropertyChanged("Prop1"); } } }
public DateTime DateProp1 { get { if (dateProp1 == null) dateProp1 = DateTime.Now; return dateProp1; } set { if (value != dateProp1) { dateProp1 = value; OnPropertyChanged("DateProp1"); OnPropertyChanged("DateProp2"); } } } //and so on
#endregion }
public abstract class BaseModel : ObservableObject { #region fields protected int ID; #endregion public int UID { get { return ID; } set { if(value != ID) { ID = value; OnPropertyChanged("UID"); } } } public BaseModel() { } public BaseModel(BaseEntity baseEntity) { if(baseEntity != null) { this.ID = baseEntity.ID; } } }


Ответ

Если у вас первая привязка проходит с нормальной скоростью, а добавление элементов вызывает тормоза, то вы неправильно работаете с коллекцией. Большие изменения должны происходить пакетно, а единственное уведомление должно быть new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset). Как вариант, если не писать свою коллекцию, то можно менять экземпляр коллекции с соответствующим уведомлением. А вот реализация INotifyPropertyChanged на самой коллекции интересует ItemsControl куда меньше.
По коду коллекции: у вас ошибка в коде AddRange. Внутри метода вы вызываете публичный метод Add, которому глубоко наплевать на ваш флаг _suppressNotification и который рассылает всю пачку уведомлений каждый раз. Вам надо вызывать защищённый метод InsertItem. Или можете опуститься на уровень ниже и работать напрямую со свойством Items, но тогда на вашей совести будут вызовы OnPropertyChanged для Count и Item[], а также вызов CheckReentrancy
Хм. Нет. Не должно быть наплевать. Впрочем, вы перекрывате только OnCollectionChanged. Возможно, OnPropertyChanged тоже влияет.

Как правильно использовать функцию validateAuthKey() в yii2?

Я провёл исследования стандартного примера, и выяснил, что функция validateAuthKey() вообще не вызывается. Для чего она тогда нужна, как её правильно вызвать, как правильно с ней работать?
public function validateAuthKey($authKey) { Yii::info('test ================'); return $this->authKey === $authKey; }


Ответ

validateAuthKey() проверяет $authKey - хэш, который хранится в куках. Вызывается для авторизации с помощью cookie в yii\web\User::loginByCookie при $enableAutoLogin = true
protected function loginByCookie() { ... if ($identity->validateAuthKey($authKey)) { if ($this->beforeLogin($identity, true, $duration)) { $this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0); $ip = Yii::$app->getRequest()->getUserIP(); Yii::info("User '$id' logged in from $ip via cookie.", __METHOD__); $this->afterLogin($identity, true, $duration); } } ... }

Два item в RecyclerView

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


Ответ

Использовать getItemViewType(). Например
public class MyAdapter extends RecyclerView.Adapter { class ViewHolder0 extends RecyclerView.ViewHolder { ... }
class ViewHolder2 extends RecyclerView.ViewHolder { ... }
private static final int TYPE_IMAGE = 0; private static final int TYPE_GROUP = 1;
@Override public int getItemViewType(int position) { int viewType; if (groups.get ( position ).getImagePath () != null ) { viewType = TYPE_IMAGE; } else { viewType = TYPE_GROUP; } return viewType; }
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case 0: return new ViewHolder0(...); case 2: return new ViewHolder2(...); ... } } }

Vim Ресурсы По Изучению [закрыт]

Вчера открыл для себя Vim. Хочу попробовать его в качестве IDE (Java, Python, PHP), но сомневаюсь в ссылках, которые нахожу.
Какие ресурсы использовади Вы, чтобы выучить Vim досконально?
Хотелось бы, чтобы описывалось все: как ставить темы, плагины, какие ставить лучше, и т.д.


Ответ

если вчера открыли, то до «досконального знания» вам ещё не один год изучать эту программу. а чтобы начать пользоваться, пройдите «быстрый курс»:
$ vimtutor ru
следующий шаг: освоение пользованием встроенной справкой. для этого запустите программу, введите :help и нажмите enter
и, конечно, никаких «тем, плагинов», пока хоть немножко не освоитесь.

Хорошая практика в подгрузке списка

У меня есть метод который возвращает некоторое количество записей и общее их число в json, ответ примерно выглядит так:
{ hits:100 ...тут идут переданные записи }
В параметрах запроса можно указать два параметра limit - число передаваемых записей и page сдвиг по записям на limit. Записей может быть около 1000 и грузить их сразу все очевидно нельзя. Я сделал некоторое подобие автоматической подгрузки, работает оно примерно так:
Делается превый запрос с page 0 и limit 50 После разбора ответа смотрим hits и делаем запрос еще раз. Повторять до достижения цели
Мне не нравится несколько моментов
Грузятся сразу все элементы При обновлении списка RecyclerView перескакивает на первый элемент
Как лучше поступить с этими двумя проблемами?


Ответ

// 1. У вас на экране не все, только то что видите, все остальные элементы дестроятся, как только "ушли" за пределы экрана.
// Для сохранения текущей позиции запомните высоту списка до //обновления, к примеру через `OnScrollListener`:

// private int mScrollY; // private RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() { // @Override // public void onScrolled(RecyclerView recyclerView, int dx, int dy) { // super.onScrolled(recyclerView, dx, dy); // mScrollY += dy; // }
// };
// После обновления данных вызывайте программно скролл
// mRecyclerView.scrollBy(0, mStateScrollY);
UPDATE Со временем было вычитано более правильное решение. Добавьте метод в ваш адаптер для RecyclerView
public void setData(List data) { mStringData.addAll(data); // ваша коллекция данных для адаптера notifyItemInserted(getItemCount() - data.size()); }
Как следствие без велосипедов адаптер добавит еще элементы в конец списка, без каких либо подергиваний или запоминании позиции скролла на экране.

Целесообразность создания экземпляров Point при задании позиции

Здравствуйте! Данный вопрос касательно оптимальности.
Каким способом из двух, при программном создании элемента управления в WinForms, лучше задавать координаты?
1) element.Location = new Point(x, y); 2) element.Location.X = x; element.Location.Y = y;
Целесообразно ли инициализировать экземпляр Point (хотя занимает меньше места и выглядит красивее)?


Ответ

2) element.Location.X = x; element.Location.Y = y;
Этот вариант не рабочий. В Location можно записать Point целиком, а доступ к Location.X и Location.Y только для чтения, т.к. Location свойство а не переменная или поле, о чем студия предупреждает еще до компиляции.
Причина довольно простая - структуры в .NET относятся к типам значениям (value types), следовательно свойство при обращении к нему предоставляет копию значения Point и вносить в нее изменения не имеет ни какого смысла.

Как на Java записать символы валют в CSV файл для корректного импорта в Excel

При импорте получившегося CSV файла в Excel знаки валют, кроме € и $ заменяются на ?. В Notepad++ все отображается нормально.
String data = "$,€,₪,₴,zł,kr,£,..."
String fileName = "C:\\Program Files\\Java\\apache-tomcat-7.0.68\\temp\\testCSV.csv";
String uncode = "UTF-8";
//uncode = "UTF-8", "UTF-16", "UTF-16BE", "UTF-16LE", "Cp866", "Cp1251", "US-ASCII", "ISO-8859-1";
Пробовал разные варианты:
FileWriter out = new FileWriter(fileName); OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(fileName),uncode); PrintWriter out = new PrintWriter(fileName, uncode)); PrintWriter out = new PrintWriter (new OutputStreamWriter (new FileOutputStream (fileName), uncode)); Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), uncode));
File f = new File(fileName); FileUtils.writeStringToFile(f, data, uncode); out.append(data); //out.write(data); //out.println(data);
В чем может быть проблема?


Ответ

Я могу ошибаться, но насколько помню, MS Excel не распознает UTF-8 без BOM (Byte Order Mark), т.ч. попробуйте как-то так:
BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream("file.txt", true), "utf8")); writer.append('\uFEFF'); writer.append("мама мыла раму");
Проверка
» /usr/bin/printf "\ufeff...
" | file file.txt file.txt: UTF-8 Unicode (with BOM) text, with no line terminators
В то же время, большинству текстовых редакторов BOM не интересен, поэтому в них у вас текст отображается нормально.

вылетает OutOfMemory

есть такой код, вылетает OOM, по логам смотрел при стррте уже 30 мб heap загружено при нажатии на кнопку, еще столько же приходит, откуда такие цифры?
public class Test_Fragment extends Fragment implements View.OnClickListener {
public static final String EXTRA_ITEM_TEST = "com.just_app.diplom.item"; private ImageView view_1; private ImageView view_2; private ImageView view_3; private ImageView view_4; private TextView textViewTestWord, scoreTextView; private String mItemQuestions; private Subject_Question mSubQuest; private ObjectMapper mapper; private AssetManager mgr; private int i = 0; private int score = 0; private String mQuestion; private Uri imgUri; private boolean flag_answer = false;
public static Test_Fragment newInstance(String item) { Bundle args = new Bundle(); args.putSerializable(EXTRA_ITEM_TEST, item); Test_Fragment test_fragment = new Test_Fragment(); test_fragment.setArguments(args); return test_fragment; }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mItemQuestions = (String) getArguments() .getSerializable(EXTRA_ITEM_TEST); LoadQuestionTask loadQuestionTask = new LoadQuestionTask(); loadQuestionTask.execute(mItemQuestions); try { mSubQuest = loadQuestionTask.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }
class LoadQuestionTask extends AsyncTask { @Override protected Subject_Question doInBackground(String... params) { mgr = getActivity().getAssets(); mapper = new ObjectMapper(); try { InputStream inputStream; inputStream = mgr.open(mItemQuestions); mSubQuest = mapper.readValue(inputStream, Subject_Question.class); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } return mSubQuest; } }
@Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate( R.layout.fragment_test, container, false); init(v); onChangeQuestion(); return v; }
public void onChangeQuestion() { mgr = getActivity().getAssets(); Collections.shuffle(mSubQuest.content); if (mSubQuest.content != null && i < mSubQuest.content.size()) { try { imgUri = Uri.parse(mSubQuest.content.get(i).answer_1); view_1.setImageDrawable(getDrawable(imgUri)); view_1.setTag(mSubQuest.content.get(i).answer_1);
Uri imgUri_2 = Uri.parse(mSubQuest.content.get(i).answer_2); view_2.setImageDrawable(getDrawable(imgUri_2)); view_2.setTag(mSubQuest.content.get(i).answer_2);
Uri imgUri_3 = Uri.parse(mSubQuest.content.get(i).answer_3); view_3.setImageDrawable(getDrawable(imgUri_3)); view_3.setTag(mSubQuest.content.get(i).answer_3);
Uri imgUri_4 = Uri.parse(mSubQuest.content.get(i).answer_4); view_4.setImageDrawable(getDrawable(imgUri_4)); view_4.setTag(mSubQuest.content.get(i).answer_4);
mQuestion = mSubQuest.content.get(i).question; textViewTestWord.setText(mQuestion); } catch (IOException e) { e.printStackTrace(); } } }
public Drawable getDrawable(Uri img) throws IOException { InputStream stream = mgr.open( img.getPath().substring("/android_asset/".length())); Drawable drawableView = Drawable.createFromStream(stream, null); stream.close(); return drawableView; }
@Override public void onClick(View v) { if (i < mSubQuest.content.size()) switch (v.getId()) { case R.id.button_1: String srcimage = (String) view_1.getTag(); flag_answer = srcimage.equals(mSubQuest.content.get(i).correct_answer); custom_Toast(v); break; case R.id.button_2: String srcimage_2 = (String) view_2.getTag(); flag_answer = srcimage_2.equals(mSubQuest.content.get(i).correct_answer); custom_Toast(v); break; case R.id.button_3: String srcimage_3 = (String) view_3.getTag(); flag_answer = srcimage_3.equals(mSubQuest.content.get(i).correct_answer); custom_Toast(v); break; case R.id.button_4: String srcimage_4 = (String) view_4.getTag(); flag_answer = srcimage_4.equals(mSubQuest.content.get(i).correct_answer); custom_Toast(v); break; case R.id.next: i++; onChangeQuestion(); lock_button(true); } }
public void init(View v) { view_1 = (ImageView) v.findViewById(R.id.button_1); view_2 = (ImageView) v.findViewById(R.id.button_2); view_3 = (ImageView) v.findViewById(R.id.button_3); view_4 = (ImageView) v.findViewById(R.id.button_4); Button next = (Button) v.findViewById(R.id.next); scoreTextView = (TextView) v.findViewById(R.id.scoreTextView); textViewTestWord = (TextView) v.findViewById(R.id.textViewTestWord); view_1.setOnClickListener(this); view_2.setOnClickListener(this); view_3.setOnClickListener(this); view_4.setOnClickListener(this); next.setOnClickListener(this); }
public void custom_Toast(View toast) { String[] correct_answer = getResources().getStringArray(R.array.list_correct_answer); String[] incorrect_answer = getResources().getStringArray(R.array.list_incorrect_answer); List correct_answer_list = Arrays.asList(correct_answer); List incorrect_answer_list = Arrays.asList(incorrect_answer); Collections.shuffle(correct_answer_list); Collections.shuffle(incorrect_answer_list); Random random = new Random(); LayoutInflater inflater = getActivity().getLayoutInflater(); View layout = inflater.inflate(R.layout.custom_toast_layout, (ViewGroup) toast.findViewById(R.id.toast_layout)); TextView text = (TextView) layout.findViewById(R.id.toast_text); if (flag_answer) { lock_button(false); scoreTextView.setText("" + ++score); text.setText(String.valueOf(correct_answer_list.get(random.nextInt(5)))); } else { text.setText(String.valueOf(incorrect_answer_list.get(random.nextInt(5)))); } Toast tost = new Toast(getActivity().getApplicationContext()); tost.setGravity(Gravity.CENTER_VERTICAL, 0, 0); tost.setDuration(Toast.LENGTH_SHORT); tost.setView(layout); tost.show(); }
public void lock_button(boolean type_lock) { view_1.setClickable(type_lock); view_2.setClickable(type_lock); view_3.setClickable(type_lock); view_4.setClickable(type_lock); }
}


Ответ

Скорее всего дело в картинках. Попробуйте их не устанавливать и должно перестать падать. Решить можно грузя их библиотекой типа UIL, коя умеет уменьшать размер картинок под размер контейнера

Python и комплексный числа с рациональными действительной и мнимой частями

В Python есть встроенный модуль поддерживающий точные вычисления с рациональными числами:
from fractions import Fraction print(Fraction(2, 3) + Fraction(5, 7))
Все здорово, если учитывать, что питон по умолчанию использует длинную арифметику.
Мне недавно понадобилось использовать комплексные числа только с рациональными мнимой и действительной частями. Вот что из этого вышло:
>>> from fractions import Fraction >>> print(Fraction(2, 3) + Fraction(5, 7) * 1j) (0.6666666666666666+0.7142857142857143j) >>> print(complex(Fraction(2, 3), Fraction(5, 7))) (0.6666666666666666+0.7142857142857143j)
Fraction автоматически приводится к float. Как решить проблему?
В C++, например, можно было бы сделать следующим образом:
complex z(Fraction(2, 3), Fraction(5, 7));
Нельзя ли нечто подобное сделать в Python?
Я пока, что вижу только одно решение написать свой класс Complex, но надеюсь есть решение проще.


Ответ

Боюсь, что другого способа действительно нет.
Единственное что, хорошим тоном будет наследоваться от абстрактного класса Complex https://docs.python.org/3.5/library/numbers.html. Это не даст упустить какие-то важные методы и в итоге позволит сделать класс с интерфейсом идентичным оригинальному.

Как получить уникальный Android device ID?

Мне кажется это один из стандартных вопросов "Как присвоить юзеру уникальный ID" и я столкнулся с тем, что способы сделать это есть разные согласно этой статье на хабре, можно получать IMEI, Wi-Fi Mac адрес, Androif BlueTooth ID либо генерировать его таким образом
String deviceId = UUID.randomUUID().toString();
и прочее. И присваивать как уникальный номер юзеру. Но мне стало интересно, действительно гугл никак не реализовал стандартный алгоритм решения такой ситуации и если так, то какому все таки варианту опытные разработчики отдают приоритет, чтоб избежать возможных ошибок?


Ответ

final String ANDROID_ID = Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID);

как встроить функционал Git в программу на C++/Qt?

как встроить функционал Git в программу на C++/Qt ?


Ответ

Нужно использовать libgit2 - библиотеку на C, разработанную специально для этой цели.

Как красиво вернуть переменную через return

Допустим у меня есть метод с слушателем (для примера выбрал запрос к VK Api, он был под рукой):
private void getSubscribersInGroup() throws Exception { //Устанавливается пауза, чтобы код не выполнялся, пока //не будет получен ответ в слушатель isPause = true;
//Создаю запрос (указываю что мне нужно получить) final VKRequest request = VKApi.groups().getMembers(VKParameters.from( VKApiConst.GROUP_ID, groupId, VKApiConst.COUNT, 0));
//Посылаю запрос и устанавливаю слушатель с методами request.executeWithListener(new VKRequest.VKRequestListener() { @Override public void onComplete(VKResponse response) { //Обрабатываю ответ и получаю его в ГЛОБАЛЬНУЮ переменную subscribersCount = getCountFromJSON(response.responseString); //Отключаю паузу, чтобы код продолжился isPause = false; }
@Override public void onError(VKError e) { //По скольку это метод из API, я не могу выбрасывать Exception, //приходится прибегать к такому варианту isError = true; error = "error when requesting count: " + e.errorMessage; isPause = false; }
@Override public void attemptFailed(VKRequest request, int attemptNumber, int totalAttempts) { //Аналогично предыдущему методу isError = true; error = "onAttemptFailed when requesting count: " + "attemptNumber = " + attemptNumber + "totalAttempts = " + totalAttempts; isPause = false; } });
//Метод просто вызывает в бесконечном цикле "wait" на 100 миллисекунд, //с условием (isPause) waitResponseFromServer(); //Если была ошибка — кидаю исключение if (isError) throw new Exception(error); }
Я хочу вернуть переменную count через return, а не использовать глобальную переменную. Методы слушателя имеют доступ только к final переменным метода, поэтому я не могу напрямую обращаться к ним. Android Studio предложила вариант сделать переменную count массивом — final int[] count = new int[1];, а потом работать с первым элементом массива. Как по мне, это немного не очевидный ход, который мне не сильно нравится. Есть еще варианты вернуть из метода переменную subscribersCount так, чтобы не использовать глобальную переменную?


Ответ

У вас не получится вернуть переменную через return, так как запрос происходит асинхронно. Вы можете передавать в этот метод listener
private void getSubscribersInGroup(final OnSubscriptionListener listener)
где OnSubscriptionListener:
public interface OnSubscriptionListener { void onUpdateSubscribersCount(int subscribesCount); }
и вызывать его внутри onComplete (VKResponse response)
request.executeWithListener(new VKRequest.VKRequestListener() { @Override public void onComplete(VKResponse response) { //Обрабатываю ответ и получаю его в ГЛОБАЛЬНУЮ переменную int subscribersCount = getCountFromJSON(response.responseString); if (listener != null) { listener.onUpdateSubscribersCount(subscribersCount); }
//Отключаю паузу, чтобы код продолжился isPause = false; }
Не совсем понятно для каких целей вам ее нужно вернуть именно через return

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

Хочу устроить небольшой эксперимент, целью которого будет выяснение вопроса о необходимости избавляться от ветвлений в таких функциях как min, max, sign и abs. Каждый должен иметь возможность взять вот этот cpp файл (GitHub), скомпилировать, запустить и посмотреть на вывод в stdout. Программа выдает две колонки чисел: время работы функции с ветвлением и без него. Программа может работать долго, несколько минут (не пугайтесь, она не виснет).
Сейчас программа компилируется только в VС++ 2015 и в GCC 4.8.1 (из MinGW), а мне бы хотелось, чтобы она работала и в других компиляторах. Кто что может посоветовать сделать? От std::chrono мне не избавиться, время замерять нужно как-то более менее универсально, от int32_t тоже, так как я не знаю, вдруг у кого-то будет int размером 64 бита (мало ли). Возможно, я не во всём следую Стандарту или есть ещё какие-то ошибки?
Важно вот что: я отдаю себе отчёт, что код зависит от наличия знакового сдвига и дополнительного кода в представлении отрицательных чисел. Так и было задумано


Ответ

Приведённый код компилируется «только в VС++ 2015 и в GCC 4.8.1», так как использует возможности стандарта C++11 (а именно std::chrono и заголовочный файл cstdint). Для того, чтобы программа собиралась на компиляторах, поддерживающих исключительно более ранние стандарты, необходимо:
Использовать функциюclock из заголовочного файла ctime. Эта функция возвращает время в процессорных тактах, а потому идеально подходит для решения поставленной задачи. Заменить включение на . Оба заголовка имеют практически идентичное содержимое, однако последний был введён ещё в C99.

Как прокрутить блок при прокрутке второго блока?

Как можно осуществить такое?
У второго блока подключен jScrollPane, у него есть вертикальная и горизонтальная прокрутка.
Когда прокручиваю этот блок по горизонтали, нужно что бы первый блок тоже прокручивался вслед за ним. Каким образом это сделать можно?
Скрипт jScrollPane к первому блоку не вариант, т.к. по горизонтали он статичен.
$(function() { var block1 = $('.jspPane'); console.log(block1); var block2 = $('.event-time__time'); console.log(block2); block1.onscroll = function() { block2.scrollTop = block1.scrollTop; block2.scrollLeft = block1.scrollLeft; }; });


Ответ

Можете отслеживать скролл с помощью события onScroll, а после значения скролла присваивать другому блоку:
block1.addEventListener("scroll", function() { block2.scrollTop = block1.scrollTop; block2.scrollLeft = block1.scrollLeft; });
$(function() { var block1 = $('.jspPane'); console.log(block1); var block2 = $('.event-time__time'); console.log(block2); block1.onscroll = function() { block2.scrollTop = block1.scrollTop; block2.scrollLeft = block1.scrollLeft; }; });

Алгоритм Монтгомери

Об алгоритме удалось найти только статью на Википедии, но там написано всё непонятно для кого и непонятно кем. Поскольку я не очень силён в теории вычетов и дискретном логарифмировании, прошу помочь разобраться с реализацией, можно приводить примеры на языках c#, c, c++.
Сначала разбираемся с умножением.
Выдержки из статьи:
По данным целым числам a, b < n, r, НОД(r,n)=1 алгоритм Монтгомери вычисляет MonPro(a,b) = a * b * r^-1 mod n
Алгоритм реализует умножение чисел по модулю (a*b) mod n.
Положим r=2^k. Определим n-остаток (n-residue) числа a < n как a' = a * r mod n
Как я понял, нам нужно подобрать такое k, чтобы r > n.
MonPro вычисляет c' = a' * b' * r^-1 mod n
Как посчитать b'?
MonPro(a,b) = a * b * r^-1 mod n
Или это и есть алгоритм?
Вопрос буду дополнять по мере разбора.


Ответ

Вот фотка из моего учебника (переписывать, честно, лень). Все понятно вроде (почти код на Паскале). Надеюсю, Вам поможет. Обоснование, думаю, не надо?

Пользователь уровня базы данных

У меня на экземпляре SQL Server 2012 зарегистрированно два пользователя: ape и ais2015. Оба пользователя уровня сервера. ape у меня как администраторская учетка, а ais2015 для пользователя (работает только в режиме для чтения).
Мне необходимо ограничить для ais2015 доступ к таблице coko.or_user
Какая разница между типом пользователя Пользователь SQL без имени входа и Пользователь SQL c именем пользователя ? Как вообще используется первый вариант, ведь с помощью него даже нельзя авторизоваться с помощью SQL Server Management Studio. Я попытался ограничить доступ к таблице or_user для пользователя ais2015 командами
REVOKE SELECT ON coko.or_user TO ais2015 DENY DELETE ON coko.or_user TO ais2015
но все равно ais2015 имеет доступ к or_user. Видимо потому что эта учетка уровня сервера. Неважно что будет с ais2015, но как мне создать пользователя, который имел бы доступ ко всем таблицам базы coko кроме таблицы or_user?


Ответ

Что касается второго пункта, то возможно дело в REVOKE SELECT. REVOKE снимает разрешение, выданное ранее с помощью GRANT (либо запрещение, установленное с помощью DENY). Если разрешение/запрещение не делалось, то команда исполняется, но эффекта не имеет. Если для доступа к объекту разрешение не было выдано ранее с помощью GRANT, то для запрещения вместо REVOKE следует использовать DENY. Также своим REVOKE SELECT вы могли снять запрещение, если оно было установлено, сделав доступной выборку из таблицы.
Если делать с нуля, то для достижения того, что вы хотите, у вас должно быть примерно следующее.
Создаём логин для доступа к серверу и пользователя БД, связанного с этим логином:
USE [master] GO CREATE LOGIN [TestLogin] WITH PASSWORD=N'123' GO USE [DbName] GO CREATE USER [DbUser] FOR LOGIN [TestLogin] GO
Замечу, что в данном случае имя пользователя БД не совпадает с именем логина к серверу, но они могут и совпадать (кстати, если создавать логин через диалог в SSMS и делать ему mapping в пользователя БД, то по-умолчанию так и происходит, в связи с чем может возникнуть путаница).
Теперь разрешим пользователю чтение данных, но запретим его для выбранного объекта:
USE [DbName] GO ALTER ROLE [db_datareader] ADD MEMBER [DbUser] GO DENY SELECT ON [coko].[or_user] TO [DbUser] GO
Также, если требуется, разрешим изменения данных, но запретим их для выбранного объекта:
ALTER ROLE [db_datawriter] ADD MEMBER [DbUser] GO DENY UPDATE, INSERT, DELETE ON [coko].[or_user] TO [DbUser] GO

Что касается первого пункта (пользователи БД без логина):
USE [Test] GO CREATE USER [LoginlessUser] WITHOUT LOGIN GO
то такие пользователи часто используются для имперсонализации, т.е. выполнения действий кем-то другим от имени такого пользователя.
К примеру, можно создать процедуру, которая будет исполняться от имени определённого пользователя и делать что-то, что доступно лишь этому пользователю:
CREATE PROCEDURE DoSomething WITH EXECUTE AS 'LoginlessUser' AS BEGIN SET NOCOUNT ON;
-- делаем что-то, что доступно LoginlessUser END
Другим пользователям можно дать права на исполнение этой процедуры.
Также можно переключать контекст исполнения, для того, чтобы выполнять команды от имени кого-то:
-- сменим контекст EXECUTE AS USER = 'LoginlessUser'; GO -- делаем что-то от имени LoginlessUser GO -- вернёмся в свой контекст REVERT; GO

Ошибка в сортировке двумерного массива

void main(void) {
srand(time(NULL));
int A[N][M], circles = N + M, swap;
for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { A[i][j] = 3 + rand() % 100; } }
while (circles) { for (int i = 0; i < (circles - 1); i++) { if (*(A + i) > *(A+i+1)) /*ругается на этот if*/ { swap = *(A + i); *(A + i) = *(A + i + 1); *(A + i + 1) = swap; } } circles--; }
}
Пишет ошибку:
Error 3 error C2106: '=' : left operand must be l-value
В чём может быть дело?


Ответ

Вы пытаетесь сравнивать строки матрицы и менять их между собой, однако оператора сравнения строк матрицы и оператора присваивания int[] к int[] у вас не существует. На то и ругается.

Почему работает div?

Есть код:

текст

Я не понимаю, почему простое выражение div.insertAdjacentHTML('afterEnd', '

Пока

'); правильно работает. Разве не нужно сначала с помощью getElementById() найти элемент с id = div, присвоить этот DOM обьект переменной, а потом что-то в него вставлять. Почему это работает?


Ответ

Если элементу назначен специальный атрибут id, то можно получить его прямо по переменной с именем из значения id
Это поведение соответствует стандарту. Оно существует, в первую очередь, для совместимости, как осколок далёкого прошлого и не очень приветствуется, поскольку использует глобальные переменные. Браузер пытается помочь нам, смешивая пространства имён JS и DOM, но при этом возможны конфликты.
Но более правильной и общепринятой практикой является доступ к элементу вызовом document.getElementById("идентификатор")

Запуск activity в handler

Всем привет! Пытаюсь запустить активити в отдельном потоке с промежутком времени,код такой: И сам вопрос: все работает,активность запускается,можно ли как сделать отдельным методом или как,что бы в каждом case не писать new Handler().postDelayed(new Runnable() {
arr_imageA[i].setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
v.startAnimation(anim); mediaPlayer.start(); playSample(R.raw.click_sound); switch (v.getId()) { case R.id.imageView1: new Handler().postDelayed(new Runnable() {
@Override public void run() { startActivity(new Intent(getActivity(), a1.class)); } }, 100);
break;
case R.id.imageView2://todo копипаст startActivity(new Intent(getActivity(), a2.class)); break; case R.id.imageView3: startActivity(new Intent(getActivity(), a3.class)); break;
} }

});


Ответ

метод
public void startActivity(final Context activityContext, final Class activityClass) { new Handler().postDelayed(new Runnable() {
@Override public void run() { startActivity(new Intent(activityContext, activityClass)); } }, 100); }
В вашем коде отличие только в том, что вы запускаете разные активити, значит нужно это часть(разные активити) вынести как параметр для метода. Если посмотреть на объявление конструктора для класса Intent
public Intent(Context packageContext, Class cls)
то видим, что вторым параметром является Class cls, где означает любой тип данных (то есть Class от любого типа данных). Далее выносим этот параметр в наш собственный метод и делаем его таким Class activityClass где означает что мы хотим принимать Сlass от любого типа данных, родителем которого является Activity
Ну а затем в case передаем конкретные экземпляры Сlass соответствующих активити
startActivity(getActivity(), a1.class); //и так далле
так как родителем любой активити является Context, то выше приведенный вызов метода валиден

C++ при записи структуры в файл с помощью fwrite в файле отображаются крякозябры

Делаю лабу в универе. Есть структуры, данные которых вводятся с клавиатуры, потом записываются в файл с помощью функции fwrite(). До сих пор работал только с fstream, и проблем не возникало. Тут тоже вроде как всё сделал правильно, но на выхлопе получаю файл device.txt, а в нём сплошные крякозябры. Собираю с под линукса g++. Вся программа на гите https://github.com/rotenbergwitalik/laba6.git
код с main:
#include #include
#define DEVICE_NAME_LEN 30 #define MEASUREVALUE_NAME_LEN 30
using namespace std;
struct powerSource { float voltage; float amperage; float periodicity; };
struct measuredValue { char measuredValueName[MEASUREVALUE_NAME_LEN]; float lowBorder; float highBorder; float inaccuracy; };
struct device { char deviceName[DEVICE_NAME_LEN];// float devicePrice; int guarantee; //in month struct powerSource devicePowerSource; struct measuredValue deviceMeasureValue; }; int main() { struct device labaDevice;
cout<<"Write name of device: "; cin>>labaDevice.deviceName; cout<<"Write price of device in $: "; cin>>labaDevice.devicePrice; cout<<"Write guarantee in month: "; cin>>labaDevice.guarantee;
cout<<"Write power source for device: "<>labaDevice.devicePowerSource.voltage; cout<<"\tAmperage: "; cin>>labaDevice.devicePowerSource.amperage; cout<<"\tPeriodicity: "; cin>>labaDevice.devicePowerSource.periodicity;
cout<<"Write measure value for device: "<>labaDevice.deviceMeasureValue.measuredValueName; cout<<"\tLow border: "; cin>>labaDevice.deviceMeasureValue.lowBorder; cout<<"\tHigh border: "; cin>>labaDevice.deviceMeasureValue.highBorder; cout<<"\tInaccuracy: "; cin>>labaDevice.deviceMeasureValue.inaccuracy;
FILE* outFile; if ((outFile = fopen("device.txt", "wb")) == NULL) { cout<<"Con not open the file"< fwrite(&labaDevice, sizeof(device), 1, outFile);
fclose(outFile);
return 0; }


Ответ

Думаю, что вы просто раньше выводили поля с помощью оператора вывода в поток <<, т.е. в текстовом виде. fwrite пишет данные в бинарном виде, как есть. Режим wt меняет одно - обработку
. Если вы хотите получать все данные в текстовом виде, используйте fprintf - типа, вместо
outStream << "guarantee = " << labaDevice.guarantee << endl;
используйте
fprintf(outFile,"guarantee = %d
",labaDevice.guarantee);
Но учтите, что если потом надо будет считывать - то считывать тоже надо будет текстово. А если используете fwrite в бинарном режиме - то потом всю структуру сразу втянете одним fread в том же бинарном режиме...

Получение кода ветки на удаленном сервере

Я пытаюсь получить код из ветки удаленного репозитория:
Кто-то отправил в репозиторий ветку с названием test с помощью git push origin test. Я могу видеть ветку при помощи git branch -r, но как мне получить эту ветку?
git checkout test не работает. git checkout origin/test что-то делает, но git branch возвращает * (no branch). Я нахожусь на «no branch».
Перевод вопроса «Checkout remote Git branch » @Juri Glass


Ответ

Ответ
Перед тем, как начать работу над удалённой веткой локально, необходимо получить её (fetch). Чтобы получить ветку, необходимо сделать следующее:
git fetch origin
Эта команда обновит все удалённые ветки. Вы сможете видеть все ветки, которые можно получить:
git branch -v -a
Имея список всех веток удалённого сервера, вы можете получить код необходимой ветки для редактирования, и у вас появится её локальная рабочая копия:
git checkout -b test origin/test
Дополнение
В современном Git (>= 1.6.6), достаточно
git checkout test
(Обратите внимание, что test – это не origin/test.) чтобы выполнить волшебную операцию «делай то, что я имею в виду» и создать локальную ветку test, которая будет иметь имя origin/test на удаленном сервере.
Таким образом, в версиях Git ≥ 1.6.6, достаточно следующего:
git fetch git checkout test
Помните, что git checkout test НЕ будет работать в современном git при использовании сразу нескольких удалённых репозиториев. В этом случае воспользуйтесь git checkout -b test remote-name/test

Строка * (no branch) в выдаче git branch означает, что вы находитесь в безымянной ветке, в так называемом состоянии «detached HEAD» (HEAD указывает непосредственно на коммит и не является символической ссылкой на какую-либо ветку). Если в этой безымянной ветке вы произвели несколько коммитов, вы всегда можете создать локальную ветку вне текущего коммита:
git checkout -b test HEAD
На основе ответа @hallski и отвеа @Jakub Narębski

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

На данный вопрос уже ответили: Как создать проверку на существование записи? 1 ответ Есть переменные u_id и re_id с данными.
И есть таблица в базе данных User с ветками: id , u_id и re_id.
Необходимо запретить добавления дубликата, - когда данные с переменными u_id и re_id уже существуют в таблице
def add_rating(user_id, recipe_id, voice): conn = sqlite3.connect('db.sqlite') c = conn.cursor()
c.execute("INSERT INTO User (u_id, re_id) VALUES("+ u_id +","+re_id+")") conn.commit() conn.close()
нужна проверка, не по уникальному id , а по вносимым данным , то есть проверять данные в u_id и re_id таблицы на уникальность


Ответ

Нужно создать уникальный индекс для этой таблицы и комбинации полей:
c.execute("CREATE UNIQUE INDEX User ON t1(u_id, re_id)"); conn.commit()

Как определить прямые и ломаные движения мыши?

Как на Javascript отловить - абсолютно прямые и ломаные движения мыши, исключая кривые.


Ответ

Алгоритм и псевдокод
Здесь у нас будут присутствовать такие сущности: класс Point, контейнер Points, и переменные его типа: Input — хранит все записанные координаты мыши, Output — будет хранить точки ломаной (или отрезка, если проведена прямая линия).
К тому же, нам понадобятся функции для нахождения угла между двумя точками Angle.Find (Point, Point) и функция нахождения модуля разницы двух углов Angle.Difference (double, double)
Для решения задачи будем проходиться по всем точкам и находить примерно ровные отрезки. И да, максимальное отклонение для линии будет в константе Angle.Eps
// начало ломаной Output.Add(Input[0]); // координаты текущего отрезка Point begin Input[0]; Point end = Input[1]; // угол для сверки double angle = Angle.Find(begin, end); // обработка всех точек for (int i = 2; i < Input.Length - 1; i++) { double currentAngle = Angle.Find(begin, Input[i]); if (Angle.Difference(currentAngle, angle) < Angle.Max) { end = Input[i]; //TODO: можно также высчитывать угол по всем точкам отрезка } else { // сохраняем старый отрезок Output.Add(end); // создаём новый отрезок begin = Input[i]; end = Input [++i]; angle = Angle.Find(begin, end); } } Output.Add(end);
В результате, если все точки на одной прямой, Output будет содержать только две точки: начало и конец отрезка. Если их больше — линия ломаная. А если у ломаной линии расстояние между точками очень мало — это кривая линия. Проверка на кривую линию может быть достаточно простая:
bool crooked = false; for (int i = 1; i < Output.Length; i++) { // функция вычисления расстояния между точками и эпсилон для длины отрезков if (Point.Distance(Output[i], Output[i - 1]) < Point.Eps) { crooked = true; break; } }
На всякий случай небольшое уточнение. Я выделил Angle.Difference потому, что просто так вычитать углы нельзя — для углов в 1 и 359 градусов разница всего лишь два, а не 358. Её можно определить так:
double Angle::Difference (double a, double b) { if (a > 270 && b < 90) {// 3*Pi/2, Pi/2, если используете радианы b += 360; // 2 *Pi } else if (b > 270 && a < 90) { a += 360; } return abs(a - b); }

Рабочая JS-версия
// -- Вспомогательные функции -- function getMousePos(canvas, evt) { var rect = canvas.getBoundingClientRect(); return { x: evt.clientX - rect.left, y: evt.clientY - rect.top }; } function angleDif(a1, a2) { if (a1 > 270 && a2 < 90) { a2 += 360; } else if (a2 > 270 && a1 < 90) { a1 += 360; } return Math.abs(a1 - a2); } function angleFind(p1, p2) { return Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI; } function distance(p1, p2) { return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)); } // -- Инициализация -- var canvas = document.getElementById('myCanvas'); var answer = document.getElementById('answer'); var ctx = canvas.getContext('2d'); var input = []; var output = []; var previous = {x:-64, y:-64}; ctx.fillStyle="#CDBCFF"; ctx.fillRect(0, 0, canvas.width, canvas.height); // -- Константы -- // Отклонение в градусах, при котором прямая считается ломаной, // и появляется изгиб. SMALL_ANGLE = 9; // Расстояние в пикселях между изгибами, // меньше которого они считаются резкими. BEND_DIST = 10; // Число резких изгибов, при котором ломаная считается кривой. NEED_BENDS = 5; // -- Основные функции -- // Обрабатывает событие движения мыши. canvas.addEventListener('mousemove', function(evt) { var mousePos = getMousePos(canvas, evt); var current = {x:mousePos.x, y:mousePos.y} // не сохраняем мусорные точки if (distance(current, previous) > 2) { previous = {x: mousePos.x, y: mousePos.y}; input.push(previous); process(); output.push({x: mousePos.x, y: mousePos.y}); drawResult(); } ctx.fillStyle = "#000000"; }, false); // Отрисовывает линию. function drawResult() { if (output.length >= 2) { ctx.fillStyle="#CDBCFF"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "#000000"; ctx.beginPath(); ctx.moveTo(output[1].x, output[1].y); for (var i = 2; i < output.length; i ++) { ctx.lineTo(output[i].x, output[i].y); } ctx.stroke(); } } // Выбирает точки для отрисовки и определяет тип линии. function process() { if (input.length < 2) return; // по этим двум точкам определяется текущее направление линии var begin = input[0]; var last = null; // текущая точка var current; // текущее направление линии var angle = 0; // направление к текущей точке var curAngle = 0; // количество резких изгибов var bends = 0; // список точек для отрисовки output = []; output.push(begin); for (var i = 1; i < input.length; i++) { current = input[i]; if (!last) { if (distance(begin, current) > 2) { last = current; angle = angleFind(begin, last); } continue; } curAngle = angleFind(begin, current); // находим угол последнего изгиба if (angleDif(angle, curAngle) < SMALL_ANGLE) { // если угол мало меняется, то перейти // к следующей точке last = current; } else { // если угол большой при малом расстоянии, // то вероятно, что у нас кривая if (distance(begin, current) < BEND_DIST) { bends += 1; } // если угол большой, то у нас не прямая // нужно добавить новую точку output.push(last); begin = current; last = null; } } // убрать "Прямая" если много точек if (output.length > 1) { // можно менять число перегибов нужное для кривой if (bends >= NEED_BENDS) { answer.innerHTML = "Кривая!"; } else { answer.innerHTML = "Ломаная!"; } } } body {background-color:#FFF} #myCanvas {border:1px solid #999}

Прямая!

Проведите мышкой внутри этого прямоугольника:

 

Обнаружение машин на автостоянке

Добрый день. Пишу программу по обнаружению свободных мест на стоянке с использованием EmguCV. Имеется: изображение с пустой стоянкой, также есть видео-поток с этой же стоянки но с машинами. Вопрос в обнаружении машин, еще лучше с примерами кода (с++ также подойдет, ибо emgucv является оберткой). Каскады Хаара отбросил сразу, так как для данной задачи использовать это слишком "умно". Думаю в сторону "вычитания изображений" (т.к имеется как и пустая, так и заполненная стоянка) или "перепадов" на изображении (асфальт-авто). Так же хотелось бы услышать советы по этому поводу, т.к материалов не так много. Из найденого: Automatic Parking Lot Classification


Ответ

Боюсь, не помогут в решении этой задачи ни детектор движения (BackgroundSubtractorMOG2), ни тем более межкадровая разница.
Стоянка - это как правило улица, а значит погода и перепады освещения. Тени в конце концов, которые запросто делают свою границу с солнечной частью более контрастной по сравнению с цветом автомобиля, близкого к серому. И всё это ещё и меняется во времени. В облачно-солнечную погоду с ветром особенно ощутимо. Не зря по приведённой ссылке автор проекта уточняет, что были подготовлены разные наборы обучающих изображений под различные погодные условия. Ну и конечно нельзя не упомянуть пешеходов, да и самих водителей, снующих вокруг машин по поводу и без, и создающих бесконечные ложные срабатывания.
Алгоритмы, работающие с так называемыми feature points (точки особенностей), имеющиеся в OpenCV, для этой задачи также не работают. Даже те из них, что предназначены для оценки площадей. Вообще с улицей сложно.
На мой взгляд, тут, кроме как машинное обучение на заранее подготовленных образцах и с большим их количеством, ничто не поможет. Всё по принципу того же Хаара, от которого отказались. Необязательно именно этот алгоритм (очень вероятно, что он не подойдёт), но любой другой, который сможет по неким признакам на асфальте уловить, что в конкретно таком-то месте машины нет.
Дополнение
Как вариант, можно попытаться использовать оператор Кэнни. Этот алгоритм имеется в инструментарии OpenCV.
Возьмите два изображения одного и того же парковочного места с автомобилем и без. Попробуйте подобрать коэффициенты Кэнни для обоих изображений таким образом, чтобы на том, где есть автомобиль, было обнаружено существенно больше границ, чем на том, где автомобиля нет (как это ни парадоксально, но на "ровном, чистом, одноцветном" асфальте при определённых условиях можно обнаружить то ещё мессиво из линий/перепадов цвета).
Если сразу не получится, то перед Кэнни вставляйте размытие (этих алгоритмов в OpenCV несколько).
Далее, если получилось, берите другие два изображения с автомобилем и без того же самого парковочного места, но уже сдвинутые во времени. Например, если первая пара была с утренней съёмки, то берите вечернюю. Для второй пары пробуйте те же самые коэффициенты, что получили для первой.
В случае успеха меняйте изображения парковочного места и автомобиля на нём. И точно также пытайтесь применить те же самые коэффициенты, но уже к новым изображениям.
При наличии терпения на всё про всё уйдёт максимум пару часов, но зато будет абсолютно ясно, корректный ли выбран путь в сторону анализа цветовой разницы или следует обратиться к иным инструментам. Этот эксперимент позволит сэкономить время, если что-то пойдёт не так, либо утвердит в правоте первичных рассуждений.

Комментарии из c++/cli (dll) в с#

Как добавить комментарий в C++ CLI, чтобы потом при использовании методов данной dll в c# можно было видеть комментарии к функциям и параметрам?


Ответ

В .NET для всех языков используется стандартный подход: xml-комментарии, начинающиеся с трёх символов ///. После компиляции dll будет создан файл xml, содержащий документацию. При наличии этого файла комментарии к методам данной библиотеки будут видны в C# и любом другом языке.
Подробнее смотрите по ссылке Документация XML (Visual C++)
Чтобы файл документации создавался в процессе компиляции нужно указывать параметр /doc компилятора. Смотрите раздел "Установка данного параметра компилятора в среде разработки Visual Studio".

Не могу не отметить: хоть там и написано, что переведено вручную, но перевод настолько корявый, что лучше переключаться на английский язык, если вы им владеете. А также могу посоветовать использовать справочные материалы по другим языкам, например Комментарии к XML-документации (Руководство по программированию на C#)

Отключение стилей автозаполнения

При авто-заполнении инпутов, Chrome выставляет следующие стили для авто-заполненных полей. Как эти стили перекрыть или отключить? Именно стили, а не само по себе автозаполение.


И следующий код не отключает стили автозаполнения:
input:-webkit-autofill { background-color: transparent !important; }


Ответ

Вот что говорит MDN про :-webkit-autofill
Note: The user agent style sheets of many browsers use !important in their :-webkit-autofill style declarations, making them non-overrideable by webpages without resorting to JavaScript hacks. Cтили, добавляемые многими браузерами через user agent, содержат !important в объявлении свойства :-webkit-autofill , запрещая его перезапись без вмешательства хаков Javascript
Можно выкрутиться, применив хитрости:

1) в случае, если фон input должен быть какого-либо цвета, но не прозрачный:
input:-webkit-autofill { -webkit-box-shadow:0 0 0 50px white inset; /* можно изменить на любой вариант цвета */ -webkit-text-fill-color: #333; }
в этом случае мы заливаем содержимое input применением внутренней тени желаемого цвета поверх цвета фона, устанавливаемого user agent stylesheet в Chrome

2) можно установить задержку на анимацию "пожелтения" фона на большой промежуток времени, тем самым давая возможность пользователю ввести свои данные и не увидеть желтый фон достаточно долго:
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus, input:-webkit-autofill:active { transition: background-color 5000s ease-in-out 0s; /* выставляется желаемая задержка */ }

Подсмотрено на SO.com: Removing input background colour for Chrome autocomplete?

Как мне не искать каждый раз пользователя в Spring?

В общем при каждом обращении к котроллер в Spring мне приходится искать пользователя, создавать объект и уже работать с ним. Т.е. скажем захожу в /profile, я вытаскиваю имя авторизованного пользователя, ищу в Базе его, если всё нормально то работаю с ним. Кликаю по /index, то опять приходиться искать пользователя в базе, создаю объект и опять выстраиваю страницу под него. Как избежать поиск и создание нового объекта?


Ответ

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

Паттерн Итератор

Определение : Паттерн «Итератор» представляет доступ ко всем элементам составного объекта, не раскрывая его внутреннего представления.
Что подразумевается под "не раскрывая его внутреннего представления" ?
Хотелось бы увидеть пример когда открытое представление и закрытое.


Ответ

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

Какой тип коллекции выбрать

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


Ответ

Всё зависит от того, где и как коллекция используется, универсальной нет.
В PL/SQL коде лучше использовать ассоциативную коллекциию. Немного производительней, не надо расширять, не только числленный индех, но недоступна в SQL и нет конструктора. Также, со слов Oracle, они эфективней конвертируются в хост переменные.
В SQL, если надо сохранять как столбец в таблицах, varrays и nested tables несколько отличаются - varrays сохраняются как LOB, nested tables в собственной таблице (отсюда и название). Некоторые DML доступны для nested tables, но недоступны для varrays
Пример ассоциативной коллекции с varchar2 ключом и инициализацией из таблицы (используется схема примеров sh):
declare type items_type is table of varchar2(64) index by varchar2(64); items items_type;
function items_ctor(stmt varchar2) return items_type is type pair_row is record ( key varchar2(64), value varchar2(64) ); type refcur_type IS REF CURSOR; --return pair_row; rc refcur_type; type pairs_type is table of pair_row index by pls_integer; pairs pairs_type; ret items_type; begin open rc for stmt; fetch rc bulk collect into pairs; for idx in pairs.first..pairs.last loop ret(pairs(idx).key) := pairs(idx).value; end loop; return ret; end;
begin items := items_ctor(q'[ select 'E' || to_char(prod_id) prod_code, prod_name from products where prod_name like 'E%' ]');
<> declare key varchar2(32) := items.first; begin while key is not null loop dbms_output.put_line('item(' || key || ')=' || items(key)); key := items.next(key); end loop; end foreach; end; /
Подробнее в оф. док. "5 PL/SQL Collections and Records"