Страницы

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

суббота, 22 июня 2019 г.

Как правильно сделать редирект через .htaccess?

Как правильно сделать редирект через .htaccess?
RewriteEngine On RewriteBase / RewriteRule ^([a-zA-Z0-9_-]+)$ page.php?go=profile&id=$1 RewriteRule ^audio([0-9]+)$ page.php?go=audio&id=$1
Как сделать такой страницы site.ru/abc и site.ru/audio123

Получаю только Profile. А как получить Profile или Audio?


Ответ

В первом правиле проверить наличие audio
RewriteRule ^(?!audio)([a-zA-Z0-9_-]+)$ page.php?go=profile&id=$1 RewriteRule ^([a-zA-Z0-9_-]+)$ page.php?go=profile&id=$1
либо поменять местами условия
RewriteRule ^audio([0-9]+)$ page.php?go=audio&id=$1 RewriteRule ^video([0-9]+)$ page.php?go=video&id=$1 RewriteRule ^photo([0-9]+)$ page.php?go=photo&id=$1 RewriteRule ^([a-zA-Z0-9_-]+)$ page.php?go=profile&id=$1

SQL, cursor, перебор, добавляется две записи вместо одной

Пытаюсь с помощью курсора перебрать исходные данные и для каждой записи сделать те или иные изменения. Вот сам запрос:
DECLARE @ID bigint --id attachments DECLARE @personID BIGINT DECLARE @territoryServiceID BIGINT DECLARE @isAtClosed BIT
DECLARE @currentServerDate DATETIME = '2016-01-01 01:10:00.000' --this change GETDATE() DECLARE @BeginDate DATETIME SET @BeginDate = @currentServerDate DECLARE @periodYear INT SET @periodYear = DATEPART(YEAR,@currentServerDate) - 1
DECLARE cur cursor LOCAL STATIC FOR SELECT at.id, at.personID, at.territoryServiceID, ts.isClosing FROM Attachments at INNER JOIN Person p ON p.id = at.personID AND p.parentID IS NULL INNER JOIN TerritoryServices ts ON ts.id = at.territoryServiceID LEFT JOIN Attachments at2 ON at2.personID = at.personID AND at2.parentID = at.id AND at2.attachmentStatusID IN (2,11,12) WHERE at.attachmentStatusID = 1 AND at.causeOfAttachID = 8 AND at.endDate IS NOT NULL AND at2.id IS NULL AND p.id IN (15300000019296419,15300000018501113,15300000014988209,414674754,420940229,409531785)
OPEN cur
FETCH NEXT FROM cur INTO @ID, @personID, @territoryServiceID, @isAtClosed WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @personID_NVARCHAR NVARCHAR(MAX) SET @personID_NVARCHAR = CONVERT(NVARCHAR(MAX),@personID) PRINT '1 ('+@personID_NVARCHAR+')'
IF (@isAtClosed = 1) -- if ter of CA is closing BEGIN -- Insert error into ErrorHandlingCampainOfAttach DECLARE @ErrorDescr NVARCHAR(MAX) SET @ErrorDescr = 'TerId: ' + CONVERT(NVARCHAR(MAX),@territoryServiceID) INSERT INTO [dbo].[ErrorHandlingCampainOfAttach] ([AttachmentsID],[personID],[territoryServiceID],[periodYear],[reasonError],[addDate],[description]) VALUES (@ID, @personID, @territoryServiceID, @periodYear, 1, GETDATE(), @ErrorDescr) END ELSE BEGIN DECLARE @terAt2ID BIGINT DECLARE @isAt2Close BIT = 0 SELECT @isAt2Close = ts.isClosing, @terAt2ID = ts.id FROM Attachments at INNER JOIN TerritoryServices ts ON ts.id = at.territoryServiceID WHERE at.personID = @personID AND at.attachmentStatusID = 2 AND at.endDate IS NULL
IF (@isAt2Close = 1) -- if ter of attach is closing BEGIN -- Insert error into ErrorHandlingCampainOfAttach DECLARE @ErrorDescr2 NVARCHAR(MAX) SET @ErrorDescr2 = 'TerAttachId: ' + CONVERT(NVARCHAR(MAX),@terAt2ID) INSERT INTO [dbo].[ErrorHandlingCampainOfAttach] ([AttachmentsID],[personID],[territoryServiceID],[periodYear],[reasonError],[addDate],[description]) VALUES (@ID, @personID, @territoryServiceID, @periodYear, 2, GETDATE(), @ErrorDescr2) END ELSE BEGIN BEGIN TRY BEGIN TRANSACTION TranName -- Search active request DECLARE @ID_zapros BIGINT SELECT @ID_zapros = id FROM Attachments WHERE personID = @personID AND endDate IS NULL AND attachmentStatusID != 2 AND id != @ID IF (@ID_zapros IS NOT NULL) BEGIN -- Canseled request
-- Block #1 -- Create cancel for active request INSERT INTO Attachments (personID,orgHealthCareID,personAddressesID,territoryServiceID,attachmentProfileID,doctorID, causeOfAttachID,careAtHome,senderRequestID,senderSystemID,attachmentStatusID,beginDate,endDate,parentID,userID,registratorID, actualAttachmentID,ConflictAttachment,Node,regDate,isMigrated,isDuplicate,oldPersonID,servApplicationID,Num) SELECT at.personID,at.orgHealthCareID,at.personAddressesID,at.territoryServiceID,at.attachmentProfileID, at.doctorID, 8,at.careAtHome,NULL,NULL, 11, @BeginDate, @BeginDate, at.id, at.userID, at.registratorID, at.actualAttachmentID, NULL,NULL,at.regDate,NULL,0,at.oldPersonID,NULL,at.Num FROM Attachments at WHERE at.id = @ID_zapros
-- Set endDate for active request UPDATE Attachments SET endDate = @BeginDate WHERE id = @ID_zapros END
--Search active attach DECLARE @ID_prikrep BIGINT SELECT @ID_prikrep = id FROM Attachments WHERE personID = @personID AND endDate IS NULL AND attachmentStatusID = 2 IF (@ID_prikrep IS NOT NULL) BEGIN -- Block #2 -- Insert detach INSERT INTO Attachments (personID,orgHealthCareID,personAddressesID,territoryServiceID,attachmentProfileID,doctorID, causeOfAttachID,careAtHome,senderRequestID,senderSystemID,attachmentStatusID,beginDate,endDate,parentID,userID,registratorID, actualAttachmentID,ConflictAttachment,Node,regDate,isMigrated,isDuplicate,oldPersonID,servApplicationID,Num) SELECT at.personID,at.orgHealthCareID,at.personAddressesID,at.territoryServiceID,at.attachmentProfileID, at.doctorID, 8,at.careAtHome,NULL,NULL, 8, @BeginDate, @BeginDate, at.id, at.userID, at.registratorID, at.actualAttachmentID, NULL,NULL,at.regDate,NULL,0,at.oldPersonID,NULL,at.Num FROM Attachments at WHERE at.id = @ID_prikrep
--Set endDate for active attach UPDATE Attachments SET endDate = @BeginDate WHERE id = @ID_prikrep END
-- Attach CA INSERT INTO Attachments (personID,orgHealthCareID,personAddressesID,territoryServiceID,attachmentProfileID,doctorID, causeOfAttachID,careAtHome,senderRequestID,senderSystemID,attachmentStatusID,beginDate,endDate,parentID,userID,registratorID, actualAttachmentID,ConflictAttachment,Node,regDate,isMigrated,isDuplicate,oldPersonID,servApplicationID,Num) SELECT at.personID,at.orgHealthCareID,at.personAddressesID,at.territoryServiceID,at.attachmentProfileID, at.doctorID, 8,at.careAtHome,NULL,NULL, 2, @BeginDate, NULL, at.id, at.userID, at.registratorID, at.actualAttachmentID, NULL,NULL,at.regDate,NULL,0,at.oldPersonID,NULL,at.Num FROM Attachments at WHERE at.id = @ID
COMMIT TRANSACTION TranName
END TRY BEGIN CATCH ROLLBACK TRANSACTION TranName
-- Insert error into ErrorHandlingCampainOfAttach INSERT INTO [dbo].[ErrorHandlingCampainOfAttach] ([AttachmentsID],[personID],[territoryServiceID],[periodYear],[reasonError],[addDate],[description]) VALUES (@ID, @personID, @territoryServiceID, @periodYear, 3, GETDATE(),ERROR_MESSAGE()) END CATCH END END
FETCH NEXT FROM cur INTO @ID, @personID, @territoryServiceID, @isAtClosed END CLOSE cur DEALLOCATE cur
Запрос для курсора возвращает 6 строк(6 выбраны для примера), то есть все ID уникальные, ничего не задваивается. Далее в зависимости от определенных условий производятся те или иные действия, прошу обратить внимание на два блока действий (в комментариях называется Block#1 и Block#2), именно они ведут себя странно.
После выполнения запроса на какой-нибудь (тут тоже важно, не всегда на одной и той-же записи, бывает то на одной то на другой, а то и на двух) записи задваиваются строки с данными, то есть вставляется две строки у которых все данные кроме автоинкрементного идентификатора повторяются! Причем если откатить действия и попробовать только на этой записи на одной (то есть цикл прогнать для одной записи) все завершается отлично! Вот такие-вот злые электрические силы. Непонятно почему так происходит, подскажите кто-нибудь что не так, или в каком направлении искать решение?
P.S. триггеров на вставку данных на таблице Attachments нету. Строки всегда вставляются после всех действия, то есть допустим первое условие выполняется, вставляется строка 1, затем по второму условию вставляется строка 2, затем строка 3, и в случае если происходит задвоение строки, то она вставляется самой последней, то есть после строки 3 вставляется строка 4 идентичная строке 1 (или строке 2 когда как)


Ответ

С помощью Mike удалось найти решение данной проблемы! Тут я изложу все поподробнее вдруг кому-то поможет. Итак, начнем. Результат запроса для курсора:

... как видно никакого дублирования идентификаторов нет
С подсказкой Mike(спасибо огромное), в одно из полей (Node) записал id записи в переборе, в результате получил следующее:
В первой записи все отлично, не будем ее рассматривать. Вторая запись по списку id = 14308060, personID = 414674754. В результате произошло задвоение (Block #1), но в поле Node видим, что в конце записался идентификатор следующей по порядку записи!!!

Ниже приведен результат следующей записи:
... тут все нормально
Далее.. Пятая запись id = 148362023, personID = 15300000018501113. В результате прошло задвоение (Block #2), опять же в поле Node идентификатор следующей записи

Ниже результат следующей записи в которой все ровно:

Итак, все это навело на мысль, значения в переменных остаются прежними если в результате установки возвращается NULL, хотя в каждом цикле переменная объявляется заново. Теперь смотрим что происходит: 1. Выполняется обработка второй записи, так как у нее есть активный запрос то следующее выражение:
DECLARE @ID_zapros BIGINT SELECT @ID_zapros = id FROM Attachments WHERE personID = @personID AND endDate IS NULL AND attachmentStatusID != 2 AND id != @ID
записывает в переменную @ID_zapros идентификатор 150118746, далее выполняется все как нужно, добавляется ровно столько записей сколько нужно, последней записи, которая дублируется еще пока нет!
Далее выполняется обработка третьей записи. У данной записи активного запроса нет, поэтому следующее выражение возвращает NULL
SELECT @ID_zapros = id FROM Attachments WHERE personID = @personID AND endDate IS NULL AND attachmentStatusID != 2 AND id != @ID
но! в переменную @ID_zapros записывается не NULL(как я предполагал), а остается предыдущее значение! Вот тут то и зарыта собака. И получается что при обработке третьей записи добавляется еще одна запись в с данными о предыдущей записи...
с 5 и 6 записью все тоже самое, только уже на другом этапе...
Я думал что, так как переменная объявляется внутри цикла, то при каждом объявлении в нее будет записываться NULL, также ошибался что при установки переменной, если результат возвращает NULL, то и в переменную запишется NULL, оказалось совсем не так...
Решение довольно простое, обнулять переменную принудительно, я сделал так:
DECLARE @ID_zapros BIGINT SELECT @ID_zapros = id FROM Attachments WHERE personID = @personID AND endDate IS NULL AND attachmentStatusID != 2 AND id != @ID IF (@ID_zapros IS NOT NULL) BEGIN --Отказываем запрос
--Создаем отказ активному запросу INSERT INTO Attachments (personID,orgHealthCareID,personAddressesID,territoryServiceID,attachmentProfileID,doctorID, causeOfAttachID,careAtHome,senderRequestID,senderSystemID,attachmentStatusID,beginDate,endDate,parentID,userID,registratorID, actualAttachmentID,ConflictAttachment,Node,regDate,isMigrated,isDuplicate,oldPersonID,servApplicationID,Num) SELECT at.personID,at.orgHealthCareID,at.personAddressesID,at.territoryServiceID,at.attachmentProfileID, at.doctorID, 8,at.careAtHome,NULL,NULL, 11, @BeginDate, @BeginDate, at.id, at.userID, at.registratorID, at.actualAttachmentID, NULL,@nvar_ID,at.regDate,NULL,0,at.oldPersonID,NULL,at.Num FROM Attachments at WHERE at.id = @ID_zapros
--Закрываем дату активному запросу UPDATE Attachments SET endDate = @BeginDate WHERE id = @ID_zapros
SET @ID_zapros = NULL END
Извиняюсь за довольно большое изложения, но я впервые здесь, может что-то делаю не так вы уж простите! Еще раз спасибо всем кто откликнулся! Надеюсь это кому-нибудь поможет не напороться на те же грабли)

Ошибка конверсии void* в char* при использовании функции malloc

Почему-то ловлю ошибку конверсии void* в char* при использовании функции malloc.
char *strLine = (char *)malloc(256); strLine = memset(strLine, 0x00, 256);
Ошибка возникает именно во второй строчке. Компилятор указывает мне, мол, уважаемый пользователь, вы неверно объявили переменную strLine. Погуглил - нашёл очень похожую проблему тоже с использованием malloc, но там всё решилось добавлением этого самого **(char *)**перед malloc. Так в чём же дело? Почему мне это не помогает?


Ответ

Ну, проблема у вас во второй строчке, а не в первой: strLine имеет тип char*, а memset возвращает void*
Вы могли бы скастить возвращаемое memset'ом значение в char*. Но оно вам в принципе вовсе не нужно. Просто напишите
memset(strLine, 0x00, 256);
Вы ж всё равно уже аллоцировали память, ничего нового из memset к вам не придёт.

Самописный СМТП-сервер

Я написал СМТП сервер, но работает он некорректно вот в каком моменте: если я 1 раз подключусь к нему через телнет, он ответит нормально (рис 1-2.), но если я еще раз подключусь через другую консоль cmd, то я появится только черный экран и все(рис3):
(рис 1)
(рис 2)
(рис 3)
В последнем случае что-бы я ни вводил, на экране ничего не отобразится, и даже не залогируется моим СМТП
В первом же случае, мои команды отображаются в консоли, они логируюстя сервером и я вижу в этой консоли ответ (рис 4):
(рис 4)
Т.е., что я вижу, один клиент к нему подключается, работает нормально сервер, во всех остальных случаях он работает не корректно (верно?)
Вот как я реализовал СМТП-сервер (это win-сервис):
protected override void OnStart(string[] args) { SmtpHelper s = new SmtpHelper(this); System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(StartListen), (object)s ); }
void StartListen(object s) { try { var a = (SmtpHelper)s; a.Listen(); //запуск } catch (Exception ex) { l.Write("Error (StartListen(object s)): " + ex.ToString()); throw; }
}

public void Listen() { try { SMTP_Listener = new TcpListener(IPAddress.Any, port); SMTP_Listener.Start();
while (true) { clientSocket = SMTP_Listener.AcceptSocket();
_sessionId = clientSocket.GetHashCode().ToString();
_email.sessionId = Convert.ToInt32(_sessionId);
StartProcessing(newController); l.Write("we are there");
// System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ClientThread), SMTP_Listener.AcceptTcpClient()); }
} catch (Exception ex) { l.Write("SMTP Listen Error: " + ex.ToString()); throw; } }

void StartProcessing(ClientSessionController newController) {
try { m_ConnectedIp = ParseIP_from_EndPoint(clientSocket.RemoteEndPoint.ToString()); m_ConnectedHostName = GetHostName(m_ConnectedIp);
_email.ip = m_ConnectedIp; _email.port = 25;
SendData("220 " + System.Net.Dns.GetHostName() + " Service ready
");
//if (!clientSocket.Connected) // clientSocket.Connect(IPAddress.Any, port);
//РАБОТА С ВХОДНЫМИ ДАННЫМИ while (true) { //если есть данные, то считаем их if (clientSocket.Available > 0) { //получение команды от клиента string lastCmd = ReadLine();
//парсим команду от клиента (HELO, RCPT, DATA etc.) if (lastCmd.Trim() != String.Empty) ProceedCommand(lastCmd, newController); //break; } else { //dump: l.Write("[Socket isn't available now]"); } } } catch (Exception ex) { throw; }
}
ВОПРОС:
Подскажите пожалуйста, как мне сделать так, чтобы мой сервис мог одинаково обслужить всех подключаемых клиентов, а не только первого?


Ответ

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

Запуск задачи субпроекта в gradle

В главном проекте есть подпроект 'uploader'. (точнее просто просто папка с ещё одним gradle проектом) Мне надо, чтобы при выполнении таска в главном проекте, выполнялся таск в подпроекте. А именно таск run с определёнными параметрами. (такие как путь до собранной в главном проекте jar итп)


Ответ

В build.gradle корневого проекта надо добавить задачу, которая будет вызывать gradle в подпроекте с нужными параметрами:
task runUploader(type: GradleBuild) { buildFile = 'uploader/build.gradle' tasks = ['run'] startParameter.projectProperties = [jarDir: "/jardir"] }
и добавить зависимости, чтобы эта задача вызывалась в нужный момент, например так:
myTask.dependsOn runUploader

Получение цвета в формате RGB по положению мыши в приложении

Решил сделать настройку цвета. Создал палитру:
void render_ColorPolet(float x, float y, float w, float h, IDirect3DDevice9* pDevice) { struct D3DVERTEX { float x, y, w, h; DWORD color; };
D3DVERTEX vertices[] = { { x, y, w, h, D3DCOLOR_ARGB(255, 255, 255, 0) }, { x + w, y, w, h, D3DCOLOR_ARGB(255, 255, 0, 0) }, { x, y + h, w, h, D3DCOLOR_ARGB(255, 0, 0, 255) }, { x + w, y + h, w, h, D3DCOLOR_ARGB(255, 0, 255, 0) } };
pDevice->SetTexture(0, NULL); pDevice->SetPixelShader(0); pDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); pDevice->SetRenderState(D3DRS_ZENABLE, FALSE); pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(D3DVERTEX)); }
Получил положение курсора:
POINT mpos; GetCursorPos(&mpos); ScreenToClient(GetForegroundWindow(), &mpos); int Os_x = mpos.x; int Os_y = mpos.y;
Теперь нужно получить по этим координатам цвет, записывая например в RGB. Я решил определить макрос:
#define COLOR_A_TEST(r,g,b) D3DCOLOR_ARGB(255,r,g,b)
Осталось всего ничего, определить цвет. И тут я встрял, по многим форумам пролазил, говорят нужно юзать GetPixel. Не могу понять как, помогите пожалуйста.


Ответ

Вот так это можно сделать:
COLOREF GetWindowPixel(HWND window, int x, int y) { auto window_dc = GetDC(window); // получаем контекст устройства if(window_dc) { auto pixel = GetPixel(window_dc, x, y); // получаем цвет ReleaseDC(window_dc); // освобождаем контекст return pixel; } return CLR_INVALID; }
Обратите внимание, что функции GetDC можно передать хэндл окна равный NULL и тогда вы получите контекст экрана и соответвенно пиксель будет в координатах экрана. То есть передавая NULL можно получать цвета пикселей в глобальных координатах и вне своего окна. Таким образом, вы можете использовать функцию GetWindowPixel так:
POINT mpos = {0}; GetCursorPos(&mpos); // ScreenToClient(GetForegroundWindow(), &mpos); // int Os_x = mpos.x; // int Os_y = mpos.y; auto color = GetWindowPixel(NULL, mpos.x, mpos.y);

Composer и stable версии

Веду небольшой пакет на github (оформлен в packagist), после создания релиза 2.0.0 - он показал его как стабильный. Потом, я нашел серьезную ошибку в реализации, и на сколько я понимаю систему версионности, т.к. API не менялось, после коммита создал релиз 2.0.1 (т.е. произошли исправления, не затрагивающие API), но packagist так и считает версию 2.0.0 стабильной. Как перевести его на новую версию?
UPDATE:
{ "name": "name/name", "description": "Desctiption", "authors": [ { "name": "AuthorName", "email": "email@gmail.com" } ], "license": "MIT", "require": { "php": ">=5.3.0" }, "require-dev": { "phpunit/phpunit": "4.7.*", "satooshi/php-coveralls": "dev-master" }, "autoload": { "psr-4" : { "NameSpace\\" : "src/" } } }


Ответ

В composer.json на github можете добавить version: "2.0.1" и еще новый тег v2.0.1. На packagist есть кнопка для обновления информации.
UPD
Так же вы можете создать новую ветку 2.0 в которой вести правки минорной версии и Packagist сразу их подцепит. Дока по тегам для композера
UPD 2
По наставлению @Etki – оказывается в composer.json действительно лучше не указывать версию. Документация
Соответственно добавление тега и/или ветки с версией будет достаточно.
UPD 3
Как выяснилось, проблема была на стороне https://poser.pugx.org, который кешировал информацию о пакете.

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

Есть сервлет myServlet и фильтр MyFilter, который перехватывает обращение к сервлету. После фильтра, как я понял, должен сначала отработать сервлет, после чего он передаёт уже управление в jsp, но не понимаю как ему передать управление?
У меня получается только из фильтра сразу выдать jsp, если я перенаправляю запрос так:
request.getRequestDispatcher("myJsp.jsp").forward(request , response);
В сервлете надо сделать пару важных вычислений.


Ответ

После того как в фильтре выполнили все необходимые действия просто передавайте управление далее по цепочке:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Выполняем действия...
// Передаем управление далее chain.doFilter(request, response); }
Последним элементом в цепочке и будет сервлет.

Как скомпилировать расширение sphinxsearch под HHVM?

http://sphinxsearch.com/
Как скомпилировать расширение sphinxsearch client под HHVM? При попытке воспользоваться расширением, ранее используемым на php-fpm, выдает ошибку:
Uncaught exception: Could not open extension /usr/lib/php5/20121212/sphinx.so: /usr/lib/php5/20121212/sphinx.so: undefined symbol: zend_new_interned_string
По информации источника http://hhvm.h4cc.de/package/lostcause/sphinxsearch состояние библиотеки Not tested
Нашел мануал Converting a PHP Extension to HHVM (не заморочился) http://www.sklar.com/software/php/2015/05/07/converting-a-php-extension-to-hhvm/


Ответ

В качестве решения проблемы воспользовался библиотекой Sphinx Search PHP Client. Устанавливается через Composer, класс SphinxClient доступен в пространстве имен Sphinx. Протестировано, работает.
https://github.com/gigablah/sphinxphp

Какая максимальная длина пароля для password_hash(),sha512 и blowfish

Какая максимальная длина пароля для password_hash(PASSWORD_DEFAULT), sha512 и blowfish - crypt()?


Ответ

Если заглянуть в определение хэш-функции в википедии:
A hash function is any function that can be used to map data of arbitrary size to data of fixed size
Вывод хэш-функции (в php!) всегда представляет собой строку фиксированной длины, поэтому можете просто оценить длину любого из представленных алгоритмов на практике.
Если вопрос касается максимальной длины входных данных, то она может быть произвольной и ограничена сверху только оперативной памятью (в случае итерационного использования, недоступного, насколько понимаю, в PHP из коробки - длина может быть условно-бесконечной).

Как создать объект с помощью рефлексии?

Существует несколько вариантов для создания объекта в Java. Слышал, что есть вариант с рефлексией. Как это можно реализовать? А также в чем суть названия этого метода создания объекта?


Ответ

Class.newInstance() Constructor.newInstance() Unsafe.allocateInstance() Десериализация объекта.

Как не допустить создания дубликатов в БД

Предположим есть следующий класс, который символизирует таблицу в БД:
public class Operation { public string Detail { get; set; } public string Number { get; set; } public int EquipmentId { get; set; } }
При создании пользователем данной сущности необходимо информировать о попытке создания дубликата.
Дубликатом считается наличие объекта в бд с такими же значениями приведенных полей
Как это можно сделать?


Ответ

Наиболее предпочтительным является способ проверки на дубликат средствами самой бд.
В Entity Framework это может выглядеть например так:
воспользуемся средствами fluent api
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity() .Property(x => x.Detail) .IsRequired() .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Operation", 1) { IsUnique = true })); modelBuilder.Entity() .Property(x => x.Number) .IsRequired() .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Operation", 2) { IsUnique = true })); modelBuilder.Entity() .Property(x => x.EquipmentId) .IsRequired() .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Operation", 3) { IsUnique = true })); }
При помощи атрибута Index
public class Operation { [Index("IX_Operation", 1)] public string Detail { get; set; } [Index("IX_Operation", 2)] public string Number { get; set; } [Index("IX_Operation", 3)] public int EquipmentId { get; set; } }
будет создан индекс на основании необходимых полей и попытка вставить дубликат выкинет исключение.
Использовать это необходимо так: Метод добавляющий запись в бд должен быть обернут в блок try
try { _operationService.Add(operation); } catch(Exception ex) { //Здесь обрабатываем возникшее исключение }
если же возможность изменить структуру таблицы есть но в бд уже есть дубликаты, то тогда необходимо сначала избавиться от дубликатов и потом создать индекс.
Если же по какой либо причине изменить бд(создать необходимый индекс) невозможно то тогда можно делать проверку перед вставкой в бд, но стоит помнить что такой вариант является менее эффективным(исключение составляет когда с бд работает один пользователь), так как после проверки и перед вставкой другой пользователь может добавить запись, выглядеть это может например так:
public static bool OperationIsExist(this IQueryable src, Operation operation) { return src .Where(x=>x.Detail.Equals(operation.Detail, StringComparison.InvariantCultureIgnoreCase)) .Where(x=>x.Number.Equals(operation.Number, StringComparison.InvariantCultureIgnoreCase)) .Where(x=>x.EquipmentId==operation.EquipmentId) .Any(); }

Работа с массивами через LINQ в C#

Начинаю изучать C#, пишу личный проект в тренировочных целях, и столкнулся с такой ситуацией:
Имеется массив inputArray, содержащий 9 экземпляров некоего класса Cell. Одним из полей в Cell является массив из девяти boolean`ов PossibleValues. Требовалось найти в inputArray такие экземпляры Cell, где в PossibleValues есть всего два true и собрать эти Cell (если таковые будут) в новый массив. Я сделал это так:
Cell[] arr = inputArray.Where(x => x.PossibleValues.Where(k => k).Count() == 2).ToArray();
Далее нужно найти в arr такие пары Cell`ов, у которых PossibleValues будут полностью совпадать (т.е. оба true у них будут по одним и тем же индексам), заранее известно, что одинаковые наборы значений PossibleValues будут встречаться не более, чем по два раза. При обнаружении такой пары, нужно запомнить индексы их true и скинуть PossibleValues по этим индексам в false всем Cell в inputArray, кроме тех, что мы только что нашли. Ожидается, что таких пар может быть от 0 до 3.
Есть способ компактно это записать с помощью LINQ?
Update: Обратите внимание, что вывод осуществляется через изменение inputArray.PossibleValues, а не arr (arr это уже выборка тех Cell, где присутствуют только два true в PossibleValues). Класс Cell включает в себя не только PossibleValues, есть и другие поля, которые в задаче не важны. В одном из ответов я выложил свой вариант решения задачи.


Ответ

Вы можете легко описывать запросы к данным при помощи LINQ, но модификация данных при помощи LINQ не описывается так легко. В идеологии LINQ (как и у всего функционального программирования) предлагается не модифицировать данные, а создавать новые. Когда у вас нету модифицирующего кода, LINQ-запросы получаются легко, и функционируют так, как вы думаете. Если вы используете с LINQ код с побочными эффектами (например, изменяющий исходную последовательность), возможны «неприятности», если только вы не материализуете все LINQ-запросы заранее.
Ваша задача при помощи LINQ делается в два приёма: сначала вычисление нужных данных, а потом уж и модификация:
var result = from l in arr from r in arr where l != r && l.PossibleValues.SequenceEqual(r.PossibleValues) select new { set = new[] { l, r }, values = l.PossibleValues.ToArray() };
foreach (var task in result.ToList()) { foreach (var cell in arr.Except(task.set)) { for (int i = 0; i < task.values.Length; i++) { if (task.values[i]) cell.PossibleValues[i] = false; } } }

Обновление: Ещё немного больше LINQ:
foreach (var task in result.ToList()) { foreach (var cell in arr.Except(task.set)) cell.PossibleValues = cell.PossibleValues.Zip(task.values, (cv, mask) => cv && !mask).ToArray(); }

Помогите написать правильно criteria в Hibernate

Не могу понять как сделать сравнение в hibernate cruteria. Есть такой метод
@Override public List getPollForUpdate(IncomingSms incommingSMS) { Criteria criteria = getSession().createCriteria(PollEvent.class); criteria.add(Restrictions.eq("status", 0)); criteria.add(Restrictions.eq("call.callingnum", incommingSMS.getSourceAddress())); return criteria.list(); }
Он должен вернуть список объектов. Но ворачивает ошибку. ругается на criteria.add(Restrictions.eq("call.callingnum", incommingSMS.getSourceAddress()));
В классе PollEvent есть поле call вот оно
@OneToOne(fetch = FetchType.EAGER) @JoinColumn(name = "CALL_ID", nullable = false) private Calls call;
а у него есть поле callingnum по которому яи хочу сравнить
@Column(name = "CALLINGNUM", length = 15) private String callingnum;
Ошибка которую я получаю
could not resolve property: call.callingnum of: polls.entety.PollEvent


Ответ

В этом случае необходимо создать либо вложенный criteria
Criteria criteria = getSession().createCriteria(PollEvent.class); criteria.add(Restrictions.eq("status", 0)); criteria.createCriteria("call") .add(Restrictions.eq("callingnum", incommingSMS.getSourceAddress()));
либо использовать alias
Criteria criteria = getSession().createCriteria(PollEvent.class); criteria.add(Restrictions.eq("status", 0)); criteria.createAlias("call", "c"); criteria.add(Restrictions.eq("c.callingnum", incommingSMS.getSourceAddress()));
Документация

оплата онлайн PayPal

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


Ответ

Давно занимался этим.. Тогда частным лицам из России нельзя было принимать оплату, поэтому я, будучи в Таиланде, открывал там счёт и к нему привязывал якобы Тайский аккаунт PayPal, на который принимал оплату. Потом такой же трюк делал, когда был в Италии. Что-то наверняка поменялось за пару лет, и вроде бы, теперь можно принимать оплату не-юрлицам и в РФ.
Доступные сервисы PayPal зависят от страны, в которой зарегистрирован аккаунт.
Простой вариант приёма оплаты на сайте доступен во всех странах.
Напр. для России доступны какие-то из решений по приёму платежей, но какие из них – только для юр. лиц, а какие есть и для частных лиц – я не знаю, надо разбираться.

Как реализовать поиск по ключу объекта?

Есть функция которая ищет value в объекте. Как можно сделать так, чтоб искать можно было по ключу?
Например сейчас работает так :
когда у функции search('r', items) аргумент rm то выдаст слова где есть r.
// ["bar", "lorem", "dolor"]
А было б неплохо если можно было искать и по ключам. Например так :
если аргументом будет foo, должно выдать: // ["bar", "lorem", "dolor"]
а если аргумент bar то должно выдать: ["amet","ipsum","dolor"]
вся функция :
function search(s, arr) { var matches = []; for (var i = arr.length; i--;) { for (key in arr[i]) { if (arr[i].hasOwnProperty(key) && arr[i][key].indexOf(s) > -1) matches.push(arr[i][key]); } } return matches; }; var items = [{ "foo": "bar", "bar": "sit" }, { "foo": "lorem", "bar": "ipsum" }, { "foo": "dolor", "bar": "amet" }]; search('r', items); // ["bar", "lorem", "dolor"]


Ответ

Аналогично же:
function search(s, arr) { var matches = [];
for (var i = arr.length; i--;) { for (key in arr[i]) { if (arr[i].hasOwnProperty(key) && key.indexOf(s) > -1) { matches.push(arr[i][key]); } } } return matches; };
var items = [{ "foo": "bar", "bar": "sit" }, { "foo": "lorem", "bar": "ipsum" }, { "foo": "dolor", "bar": "amet" }];
search('foo', items);

Стеки фиксированного размера и очередь с max за O(1)

При помощи очереди с нахождением максимума за O(1) надо обрабатывать миллиарды элементов. Чтобы программа работала быстрее, нужно придать фиксированный размер двум стекам, при помощи которых моделируется очередь. Как это сделать правильно? Мои попытки:
AmpQueue(int size){ std::vector< std::pair > v_temp; v_temp.resize(size); std::stack< std::pair, std::vector< std::pair > > s_temp(std::move(v_temp)); s1.swap(s_temp); s2.swap(s_temp); }
А вот и сама программа:
#include #include #include #include
// Класс для эффективного нахождения максимальной // амплитуды на подотрезке class AmpQueue{ private: std::stack< std::pair, std::vector< std::pair > > s1, s2; public: AmpQueue(); AmpQueue(int size){ std::vector< std::pair > v_temp; v_temp.resize(size); std::stack< std::pair, std::vector< std::pair > > s_temp(std::move(v_temp)); s1.swap(s_temp); s2.swap(s_temp); } // Загрузка нового элемента в очередь с поддержной нахождения максимума void push(int new_element){ int max = s1.empty() ? new_element : std::max (new_element, s1.top().second); s1.push(std::make_pair(new_element, max)); } // Удаляет элемент из очереди и возвращает значение удаленного элемента int pop(){ if(s2.empty()) while(!s1.empty()){ int element = s1.top().first; s1.pop(); int max = s2.empty() ? element : std::max(element, s2.top().second); s2.push(std::make_pair(element, max)); } int result = s2.top().first; s2.pop(); return result; } // Получение текущего максимума в очереди за O(1) int max(){ if(s1.empty() || s2.empty()) return s1.empty() ? s2.top().second : s1.top().second; else return std::max(s1.top().second, s2.top().second); } // Проверка: пуста ли очередь bool empty(){ return (s1.empty() && s2.empty()); } // Загрузка в очередь последовательности из n чисел void load(int n){ int value; while(n--){ std::cin >> value; push(value); } } };
int main(){ int n, current, maximum, element;
std::cin.sync_with_stdio(false); std::cin >> n; AmpQueue q(n);
// Загрузим в очередь первые n значение амплитуды q.load(n); // Выведем текущий максимум std::cout << q.max() << std::endl;
// Загружаем следующий элемент последовательности и ищем максимум std::cin >> current; while(current != -1){ q.pop(); q.push(current); std::cout << q.max() << std::endl; std::cin >> current; } }
Программа сначала крашилась при запуске, а после исправлений стала выдавать одни и те же числа. Возможно, этот код совсем плохой, потому что вчера я редактировал его уже только на идеоне. Поэтому показываю код на идеоне:
https://ideone.com/bJUpwL
Предполагаю, что проблема в том, что два стека уже заполнены нулевыми парами и имеют размер n, поэтому при добавлении новых элементов они укладываются сверху на существующие нулевые элемента. Из-за этого алгоритм работает неправильно (точнее, из-за условия empty).
Как все исправить?


Ответ

Попробуйте использовать std::vector::reserve() вместо std::vector::resize(). Но в push() вам нужно контроллировать верхний размер в любом случае.
Ваш поправленный пример, не могу оценить насколько он работающий: https://ideone.com/uF09OU

Гибридное управление памятью

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


Ответ

Скорее всего вам подойдёт C++/CLI. Это Microsoft'овский гибрид C++ и платформы .NET.
В нём .NET-объекты создаются при помощи gcnew и управляются сборщиком мусора, а стандартные C++-объекты создаются при помощи new и удаляются вручную через delete

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

Каким образом можно добавить класс, чтобы для него присвоить знак открытой-закрытой вкладки? Сложность в том, что везде коды сильно отличаются. Пример Код скрипта.
jQuery(function($){ $('.multi-accordion li > a').on('click', function (event) { var $this = $(this), $next = $this.next(); if ($next.length) { $next.toggle().parent().toggleClass('opened').siblings().children('ul').filter(':visible').toggle(); event.preventDefault(); } }); });



Ответ

$('.multi-accordion li > a').next().parent().addClass('has-children')
Первая строка отвечает за выборку li > a в блоке с классом multi-accordion и для тех, кто является родителем присваивается класс has-children
$('.multi-accordion .has-children > a').click(function(e) { var li = $(this).parent();//получаем сам li //ищем все элементы на этом уровне и ниже с классом open, который показывает, что элемент раскрыт li.parent('ul').find('.open') //добавляем текущий элемент если он до этого был схлопнут .add(li) //меняем состояние классов has-children и open у выбранных элементов .toggleClass('has-children open');
// запрещаем поведение по умолчанию, конкретно здесь - переход по ссылке. e.preventDefault(); });
$('.multi-accordion li > a').next().parent().addClass('has-children') $('.multi-accordion .has-children > a').click(function(e) { var li = $(this).parent(); li.parent('ul').find('.open').add(li).toggleClass('has-children open').children('ul'); e.preventDefault(); }); .col-left-first { box-sizing:border-box; display: block; position: relative; width: 240px; margin-left: 240px; box-sizing: border-box; } .multi-accordion-catalog { display: block; position: relative; width: 100%; box-sizing:border-box; } .multi-accordion { line-height: 40px; margin: 0; color: #646464; padding: 0; font-family: "Helvetica Neue", Arial, sans-serif; font-weight: normal; font-size: 16px; text-transform: none; } .multi-accordion ul { display: none; list-style: none; padding: 0px; } .multi-accordion li { list-style: none; } .multi-accordion > li > a{ } .multi-accordion > li > ul { padding-left: 8px; } .multi-accordion > li > ul > li > ul { padding-left: 8px; } .multi-accordion a, .multi-accordion a:link, .multi-accordion a:visited { display: block; text-decoration: none; padding: 0 24px 0 10px; color: #646464; position: relative; } .multi-accordion a:hover { } .multi-accordion > a:only-child:link, .multi-accordion > a:only-child:visited { color: blue; } .multi-accordion > a:only-child:hover { text-decoration: underline; background: transparent; } .multi-accordion-title { display: inline-block; position: relative; width: 100%; padding-right: 40px; margin-bottom: 12px; box-sizing:border-box; } .multi-accordion-title:after { content: ''; position: absolute; width: 0; height: 0; border-style: solid; top: 100%; left: -12px; border-width: 0 12px 12px 0; border-color: transparent #cccccc transparent transparent; } .catalog-title { display: inline-block; position: relative; box-sizing:border-box; line-height: 40px; width: 100%; font-family: "Helvetica Neue", Arial, sans-serif; font-weight: 600; font-size: 16px; text-transform: uppercase; background-color: #e1e1e1; padding-left: 10px; box-shadow: -4px 4px 4px rgba(0, 0, 0, 0.2); } .catalog-title:before { content: ''; position: absolute; top: 0; left: -12px; height: 100%; width: 12px; background-color: #e1e1e1; } .catalog-title:after { content: ''; position: absolute; top: 0; left: 100%; border-style: solid; border-width: 0 0 40px 40px; border-color: transparent transparent transparent #e1e1e1; } .has-children, .open { position: relative; } .has-children > a:before , .open > a:before { content: ''; position: absolute; height: 24px; width: 24px; top: 8px; right: 4px; } .has-children > a:before { background: url(https://cdn2.iconfinder.com/data/icons/ios-7-icons/50/down4-16.png) no-repeat; } .open > a:before { background: url(https://cdn1.iconfinder.com/data/icons/mayssam/512/Top_2-16.png) no-repeat; } .multi-accordion .open > ul { display: block; }


Нарушает ли приложение авторские права? [закрыт]

Мое приложение рандомно предлагает фильм по некоторым параметрам. Результат работы показывается пользователю в виде постера фильма и краткой информации о нем: описание, год, страна. Все данные взяты из отрытых источников. Есть ли вероятность что приложение будет заблокировано за нарушение авторских прав? Ссылку не прилагаю, дабы не сочли за рекламу.


Ответ

Нет, это же справочник. Вы же не фильмы показываете.

Автодополнение для Си

Меня интересует автодополнение кода для Си в Sublime Text 3. Мне нужно, чтобы после подключения заголовка какой-то плагин давал подсказки, подобно intellisense из Visual Studio. Я "нагуглил" какие-то Clang autocomplete и тому подобное, но они нормально не работают.
Все мои плагины:

Из автодополнений у меня есть ключевые слова а-ля struct, typedef, типы переменных etc. Но нет автодополнения (или, можно сказать, подсказок) по подключаемым файлам. Например, тот же stdio.h — у меня автоподолнение только ОДНОЙ функции printf.


Ответ

Попробуйте вот это. Он, технически, должен выбирать все функции, из заголовков, что у вас подключены. Подробнее про установку на Хабре
Если у вас линукс, то можно заставить его работать под ST3, но вроде бы и под виндой можно

Msg 9002 The transaction log for database 'myDataBase' is full due to 'ACTIVE_TRANSACTION

Есть база данных myDataBase в ней есть таблица myTable в таблице около двух миллионов записей. При попытке добавить столбец к этой таблице
ALTER TABLE dbo.myTable ADD myTable_id int identity(1,1) not null primary key
получаю ошибку:
Msg 9002 The transaction log for database 'myDataBase' is full due to 'ACTIVE_TRANSACTION'.**
Из сообщения понятно что переполнен журнал transaction log
После этого увеличил размер log файла:
ALTER DATABASE myDataBase MODIFY FILE (NAME = myDataBase_log , MAXSIZE = 170MB) GO
и применил команду:
CHECKPOINT DBCC SHRINKFILE ('myDataBase_log')
До выполнения команды: ALTER TABLE dbo.myTable ADD myTable_id int identity(1,1) not null primary key размер log файла 27MB после 150MB и всё равно ошибка Msg 9002. Подскажите как в данной ситуации поступить:
Увеличивать размер log файла? если увеличивать то на сколько? Нормальное ли это поведение log файла?


Ответ

Да, это нормальное поведение.
SQL Server немедленно пишет все вносимые вами изменения в transaction log.
Ваш ALTER требует полного пересоздания таблицы - т.к. вы добавляете кластерный индекс. Соответственно, в лог будут записано удаление старых данных + вставка их заново, с попутным пересозданием всех индексов. Так что объем лог-файла стоит увеличить минимум до 2x размера таблицы (лучше 4x).
Я бы на вашем месте выставил размер лога не исходя из размера базы, а исходя из доступного места на диске (т.е. все свободное место минус минимальный запас). или вообще снял ограничение.
Размер таблицы + размер индексов можно посмотреть в View / Object Explorer Details в Management Studio.

Регулярное выражение для nickname (Вид: “Имя(с большой буквы)_Фамилия(с большой буквы)”)

Требуется регулярное выражение которое будет допускать nickname только такого типа:
Имя(с большой буквы)_Фамилия(с большой буквы)
^(([a-zA-Z]{4,12})([_]{1})([a-zA-Z]{4,12}))$
Использую вот такое, но фамилию можно записать с маленькой


Ответ

Ну вот, очень простая регулярка:
^([A-Z][a-z]{3,11})_([A-Z][a-z]{3,11})$
2 селектора, 1й - имя, 2й - фамилия. И имя, и фамилия обязательно начинаются с большой буквы, остальные буквы в нижнем регистре, так же знак подчеркивания обязателен и пробелы недопустимы.
Если есть желание допустить полный upper-case, можно привести это к следующему виду:
^([A-Z][a-zA-Z]{3,11})_([A-Z][a-zA-Z]{3,11})$
Здесь регулярку можно опробовать на лету: https://regex101.com/

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

Есть DDS DoubleNode, которая является двунаправленным списком:
public class DoubleNode { public int value; public DoubleNode prev; public DoubleNode next;
public DoubleNode(int value, DoubleNode prev, DoubleNode next) { this.value = value; this.prev = prev; this.next = next; }
а вот что я пытаюсь сделать, так это построить такую Node, зная только количество элементов в ней (значения элементов выбираются случайно). При всем при этом построить хочу рекурсивно, сваял вот такой метод:
public static DoubleNode doubleNodeGenRec (int length) { return (length == 0) ? null : new DoubleNode((int)(Math.random()*10), null, doubleNodeGenRnd(--length)); }
как новому элементу передать ссылку на DoubleNode prev;?
выходит, что строится Node в одну сторону, т.к. в методе туда передается просто null, и в результате выходит просто связанный список. чем заменить этот null?


Ответ

public DoubleNode(int value) { this.value = value; }
public static DoubleNode doubleNodeGen(int length) { return doubleNodeGenRec(length, null); }
private static DoubleNode doubleNodeGenRec(int length, DoubleNode prev) { if (length == 0) { return null; }
int value = (int) (Math.random() * 10); DoubleNode node = new DoubleNode(value); node.prev = prev; node.next = doubleNodeGenRec(length - 1, node); return node; }

Почему родитель формы равен Null?

Выдержка кода из главной формы:
public partial class Main : Form { public NetComm.Host server; public NetComm.Client client; public Main() { InitializeComponent(); } private void ToolStripMIConnect_Click(object sender, EventArgs e) { ClientPref formConnect = new ClientPref(); formConnect.Owner = this; formConnect.ShowDialog(); } }
Выдержка кода из создаваемой формы:
public partial class ClientPref : Form { Main formMain; public ClientPref() { InitializeComponent(); formMain = this.Owner as Main; } private void btnConnect_Click(object sender, EventArgs e) { if (formMain != null) //следующий бок не выполняется т.к. formMain равен null { if (IsAddressValid(this.txtBoxIP.Text)) { formMain.ClientStart(Convert.ToInt32(this.txtBoxPort.Text), this.txtBoxIP.Text, "Соперник"); } else toolTipClient.Show("Введен некорректный IP-адрес.", this.txtBoxIP); }
}
Почему formMain равен null или как в итоге обратиться к методу ClientStart формы Main?


Ответ

Простой вариант - переписать вот так, сделать поле вычислимым свойством:
Main FormMain { get { return this.Owner as Main } };
Тогда в btnConnect_Click всё должно работать.

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

Есть класс для работы с IMAP протоколом. Назовем его class1 А так же есть класс для работы с сокетами. Назовем его class2 Я хочу из class1 дергать методы class2. Нужно все два метода - socketRequest($socketRequest) и socketResponse(). Т.е отправить запрос и принять ответ. Как реализовать подобное?
Идея 1: передать в конструктор class1 объект class2 и потом уже вызывать нужные методы. Но тогда получается, что классы жестко связаны.
Идея 2: В class2 реализовать __invoke($socketRequest). Далее как так же передаю объект class2 в class1, но в отличие от первой идеи, я не вызываю конкретные методы а сам объект использую как функцию - class2($imapRequest). Т.е привязки сильной нету, можно потом будет подсунуть все что хочешь. Какие идеи?


Ответ

Вашу задачу можно решить с помощью одного из следующих типов отношений - агрегация, либо композиция
Агрегация – применяется когда один класс должен быть контейнером других классов. Причем время существования содержащихся классов никак не зависит от времени существования класса контейнера.
пример:
class class2 { public function socketRequest($socketRequest) { // } public function socketResponse() { // } }
class class1 { private $foo;
public function __constructor(class2 $Foo) { $this->foo = $Foo; }
public function socketRequest($socketRequest) { return $this->foo->socketRequest($socketRequest); } public function socketResponse() { return $this->foo->socketResponse(); } }
Если в ходе выполнения программы объект class1 будет уничтожен, это никак не повлияет на объект класса class2
Композиция более строгий вариант отношений. В отличии от агрегации, композиция имеет жёсткую зависимость времени существования экземпляров класса контейнера и экземпляров содержащихся классов.
пример:
class class2 { public function socketRequest($socketRequest) { // } public function socketResponse() { // } }
class class1 { private $foo;
public function __constructor() { $this->foo = new class2; }
public function socketRequest($socketRequest) { return $this->foo->socketRequest($socketRequest); } public function socketResponse() { return $this->foo->socketResponse(); } }
Если в ходе выполнения программы объект class1 будет уничтожен, это повлечет за собой уничтожение объекта класса class2
Чтобы определить какой тип отношений Вам подходит нужно ответить на вопрос должен ли класс class2 существовать вне класа class1. Если class2 планируется использовать где то еще - используйте агрегацию, если нет - композицию.

Открывающие и закрывающие скобки в RegExp

Как с помощью регулярного выражения проверять наличие закрывающей и открывающей скобки или каких-либо других парных символов? К примеру, имеется строка состоящая из 32 шестнадцатеричных чисел, которая может быть в круглых скобках, фигурных, квадратных, меньше-больше. На данный момент имею выражение:
var re = new RegExp("([\(][0-9A-Fa-f]{32}[\)]|[0-9A-Fa-f]{32})");
Но как видно из примера, с таким подходом для каждой новой пары символов придется полностью повторять первую часть выражения. В случае использования одинаковых открывающих и закрывающих символов можно было бы написать так:
var re = new RegExp("((["'`´])[0-9A-Fa-f]{32}\2|[0-9A-Fa-f]{32})");
, т.е. можно обратиться к запоминающей скобке по ее индексу, но с парными символами такое не пройдет. Может быть существует более лаконичное выражение, чем:
var re = new RegExp("("+ "[\(][0-9A-Fa-f]{32}[\)]|"+ "[\{][0-9A-Fa-f]{32}[\}]|"+ "[\[][0-9A-Fa-f]{32}[\]]|"+ "<[0-9A-Fa-f]{32}>|"+ "[0-9A-Fa-f]{32})" );


Ответ

Есть несколько путей решить задачу, например такой будет работать в JavaScript:
/(?=(?:\(.*\)|\[.*\]|<.*>|\{.*\}|[0-9a-f]*)$)^[\[{(<]?[0-9a-f]{32}[\]}>)]?$/i
Используются позиционные проверки.
Следующий способ в JavaScript работать не будет, потому что использованы условия, которые движком не поддерживаются.
/^(<)?(\()?(\{)?(\[)?(?<=^.?)[0-9a-f]{32}(?(1)>|(?(2)\)|(?(3)\}|(?(4)\]|))))$/i

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

не загружается модуль yatank_OnlineRep

Как я понял старый плагин онлайн-графиков канул в лету (http://clubs.ya.ru/yandex-tank/replies.xml?item_no=510) и ему на смену пришел yatank-online. Пробую им воспользоваться и на старте Танка получаю ошибки следующего рода:
14:53:00 INFO: Loading configs... 14:53:00 INFO: Loading plugins... 14:53:00 INFO: Exception: Traceback (most recent call last): File "/usr/lib/yandex-tank/Tank/ConsoleWorker.py", line 183, in configure self.core.load_plugins() File "/usr/lib/yandex-tank/tankcore.py", line 233, in load_plugins instance = self.__load_plugin(plugin_name, plugin_path) File "/usr/lib/yandex-tank/tankcore.py", line 257, in __load_plugin exec ("import " + classname) File "", line 1, in ImportError: No module named yatank_OnlineRep
14:53:00 ERROR: No module named yatank_OnlineRep 14:53:00 ERROR: Exception: No module named yatank_OnlineRep

Сам модуль ставился пипом и по-умолчанию лег в /usr/local/lib/python2.7/dist-packages/yatank_OnlineReport/ в то время как основные плагины лежат в /usr/lib/yandex-tank/Tank/Plugins/. По каким путям, кроме своего родного дира, Танк еще ищет и как его завернуть в нужное место?
Ubuntu 1404 Tank 1.6.8 (ppa installed) yatank-online 0.0.5 (pip installed)


Ответ

У вас старый танк, текущая версия 1.7.28. Начиная с ветки 1.7 изменился способ импортирования плагинов (теперь это стандартный питонячий импорт). Поставьте 1.7.28 -- должно заработать.
UPD: начиная с ветки танка 1.8 мы потеряли совместимость с этим плагином. Старый код сохранен тут, эта же версия сейчас в PyPI. Совместимость с новой версией in progress, работа идет в мастере репозитория.
Вместо плагина онлайн отчета советую использовать сервис Overload. Это бесплатно и там больше возможностей.
Если все-таки хочется плагин, то ставить так:
pip install https://api.github.com/repos/yandex-load/yatank-online/tarball/master

Как нарисовать рваную линию?

Есть ли возможность, стандартная, а если и нет, то скажите, как можно нарисовать рваную линию, похожу на баллончик, или рваную кисть, которая не полностью зарисовывает область, а как бы оставляет след. Я реализовываю такую вот штуку. Заранее, спасибо за помощь.
[Обновление] Задача упростилась, теперь просто нужно узнать как рисовать линию изображением.


Ответ

Я так понимаю, единственный вариант это накладывать одно и то же изображение снова и снова, каждый раз, когда курсор смещается.
В том примере, который у вас просто рисуется одно и то же изображение, именно так, как я описал в комментарии выше. просто изображение необычной формы и по краям, судя по всему есть полупрозрачные пиксели.
если предположить, что у вас есть заднее изображение и переднее. то вам надо по клику в переднем изображении создавать прозрачный кусок установленной формы. вот пример с SO как это сделать
// get access to the image bytes CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
// create a buffer to hold the mask values size_t width = CGImageGetWidth(image.CGImage); size_t height = CGImageGetHeight(image.CGImage); uint8_t *maskData = malloc(width * height);
// iterate over the pixel data, reading the alpha value uint8_t *alpha = (uint8_t *)CFDataGetBytePtr(pixelData) + 3; uint8_t *mask = maskData; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { *mask = *alpha; mask++; alpha += 4; // skip to the next pixel } }
// create the mask image from the buffer CGDataProviderRef maskProvider = CGDataProviderCreateWithData(NULL, maskData, width * height, NULL); CGImageRef maskImage = CGImageMaskCreate(width, height, 8, 8, width, maskProvider, NULL, false);
// cleanup CFRelease(pixelData); CFRelease(maskProvider); free(maskData);
Потом, чтобы все это запустить сделать:
CGImageRef subtractedImage = CGImageCreateWithMask(b.CGImage, maskImage);
Еще добавлю, что этот фокус скорее всего будет есть очень много ресурсов для большой картинки. может есть смысл поделить на несколько маленьких.

Виртуальные методы

Можно ли вызывать виртуальные методы в конструкторах и деструкторах классов?


Ответ

Да, можно. Но не рекомендуется
При вызове виртуального метода в конструкторе, будет вызвана функция (пере)определенная в этом классе, и одном из его базовых классов, но не в классах потомках, т.к. они еще не сконструированы.
В деструкторе происходит то же самое, класс-потомок уже разрушен, и его функции не могут быть вызваны. Поэтому будет вызована функция, определенная в этом классе или его базовых классах.
struct A { virtual void f() = 0; virtual void g() { std::cout << "A::g "; } };
struct B : A { B() { f(); // будет вызвана B::f g(); // будет вызвана A::g } void f() override { std::cout << "B::f "; } };
struct C : B { // не будут вызваны из конструктора B void f() override { std::cout << "C::f "; } void g() override { std::cout << "C::g "; } };
C c; // выведет B::f A::g
Релевантная цитата из стандарта, 12.7 Construction and destruction [class.cdtor] p4
Member functions, including virtual functions (10.3), can be called during construction or destruction [...] If the virtual function call uses an explicit class member access (5.2.5) and the object expression refers to the complete object of x or one of that object’s base class subobjects but not x or one of its base class subobjects, the behavior is undefined.

unity3d выполнение скрипта по времени

У объекта должна меняться прозрачность, секунд на десять, а потом возвращаться в исходное состояние. Придумал вот такое:
public SpriteRenderer _sprite;
public void Invisibility () {
var color = _sprite.color; color.a = 0.4f; _sprite.color = color; StartCoroutine(Timer()); } IEnumerator Timer() { var color = _sprite.color; yield return new WaitForSeconds(10); color.a = 1; _sprite.color = color; }
Но мне кажется, это не есть хорошо.


Ответ

Тот подход, который вы используете - вполне нормальный и имеет право на жизнь.
Если бы был код на страницу, то, возможно, можно было бы что-то исправить.
А данный код можно лишь слегка подредактировать, убрав color в объявленную переменную что бы не писать var color = _sprite.color; и в функции Timer() в конце написать StopCoroutine("Timer")
Пример:
using UnityEngine; using System.Collections;
public class EnumeratorTest : MonoBehaviour {
public SpriteRenderer _sprite; private Color _spriteColor;
void Start() { _sprite = GetComponent(); _spriteColor = _sprite.color; }
public void Invisibility () { _spriteColor.a = 0.4f; _sprite.color = _spriteColor; StartCoroutine(Timer()); }
IEnumerator Timer() { yield return new WaitForSeconds(5); _spriteColor.a = 1; _sprite.color = _spriteColor; StopCoroutine ("Timer"); } }
Если еще больше оптимизировать, то можно сделать просто отдельную мааааааленьку функцию, которую можно использовать для изменения альфа канала. Вот как это в целом будет выглядеть:
using UnityEngine; using System.Collections;
public class EnumeratorTest : MonoBehaviour {
public SpriteRenderer _sprite;
void Start() { _sprite = GetComponent(); }
public void Invisibility () { SetOpacity(_sprite, 0.4f); StartCoroutine(Timer()); }
IEnumerator Timer() { yield return new WaitForSeconds(5); SetOpacity(_sprite, 1); StopCoroutine ("Timer"); }
private void SetOpacity(SpriteRenderer sprite, float opacity) { sprite.color = new Color(sprite.color.r, sprite.color.g, sprite.color.b, opacity); } }
Ну и конечно не забывать, что лучше не применять такие магические числа из головы как 0.4f, а описать их как объявленную переменную и подставить её в в функцию.
А в целом ваш код - код как код.

Как корректно проверить доступность Интернет?

Как корректно проверить доступность сети Интернет в мобильном приложении?
Включен ли доступ в Интернет на телефоне, и, даже если включен, доступна ли сеть (есть возможность загрузить или передать информацию через сеть).


Ответ

var p = NetworkInformation.GetInternetConnectionProfile(); if (p != null && p.GetNetworkConnectivityLevel() >= NetworkConnectivityLevel.InternetAccess) { // ... }

Удалить дубли в Linux по маске

Составить команду для Linux CentOS
Нужно удалить дубли с практически одинаковыми названиями, содержащими цифры в конце.
Есть:
Авария на Чернобыльской АЭС.ppt Авария на Чернобыльской АЭС 345.ppt АА Лекция 13 Ю Защита в чс ДЛЯ ЗО.ppt АА Лекция 13 Ю Защита в чс ДЛЯ.ppt Обозначения в автоматике 194.ppt Барклай де Толли.ppt
Оставить:
Авария на Чернобыльской АЭС.ppt АА Лекция 13 Ю Защита в чс ДЛЯ.ppt Обозначения в автоматике 194.ppt Барклай де Толли.ppt
fdupes удалить дубли не помог.


Ответ

Нашла на мой взгляд самое правильное решение
ls | sort -f | uniq -dw 10 | while read d; do echo "$d"; done
Команду после теста заменяем на rm и выставляем правильное количество знаков по которым ведется отбор. У меня стоит 10 но есть резон оптимизировать опытным путем

как воспользоваться сертификатами от проекта let's encrypt?

с 3 декабря 2015 года проект let's encrypt перешёл в режим "public beta".
как воспользоваться сертификатами, выдаваемыми этим проектом?


Ответ

можно воспользоваться любой из реализаций клиентов, работающих с системой let's encrypt
например, есть пошаговая инструкция для официального клиента.

но мне понравился минималистичный shell-скрипт из репозитория lukas2511, который не требует ни повышенных привилегий для своей работы, ни установки дополнительных программ/пакетов (всё необходимое обычно уже имеется в любой «серверной» установке: bash, openssl, curl и утилиты из coreutils).
как я настроил этот клиент
для пущей безопасности я создал пользователя letsencrypt (без пароля):
$ sudo adduser --disabled-password letsencrypt открыл сеанс оболочки от имени этого пользователя:
$ sudo -u letsencrypt -i letsencrypt@host:~$ склонировал репозиторий со скриптом и «перешёл» в созданный каталог:
$ git clone https://github.com/lukas2511/letsencrypt.sh.git $ cd letsencrypt.sh
если git не установлен, можно скачать архив с файлами и распаковать. скопировал образцовый конфиг:
$ cp config.sh.example config.sh создал файл domains.txt для домена (мне требуется, чтобы в сертификате были имена и с www и без):
domain.tld www.domain.tld
если требуются на этой же машине и сертификаты для других доменов, то можно добавить ещё строк в этот файл, по строке для каждого сертификата. создал каталог для аутентификации
$ mkdir .acme-challenges теперь на время надо вернуться к настройкам http-сервера. можно завершить сеанс пользователя letsencrypt, а лучше открыть другое окно с оболочкой более привилегированного пользователя.
в настройках http-сервера надо прописать alias для /.well-known/acme-challenge, чтобы он указывал на созданный в предыдущем пункте каталог. ориентировочно это будет /home/letsencrypt/letsencrypt.sh/.acme-challenges
для nginx в секцию server надо добавить location
location /.well-known/acme-challenge { alias /home/letsencrypt/letsencrypt.sh/.acme-challenges; } для apache в секцию virtualhost надо добавить строку:
alias /.well-known/acme-challenge /home/letsencrypt/letsencrypt.sh/.acme-challenges
это надо проделать для всех доменов (точнее, отдельных строк в созданном вами файле domains.txt).
http-сервер после этого надо перезапустить. теперь можно запускать скрипт для генерации сертификата(-ов). вернитесь к окну, где открыта оболочка, запущенная от имени пользователя letsencrypt (или запустите новую и перейдите в каталог со скриптом):
$ ./letsencrypt.sh -c
если всё пойдёт нормально, последней строкой выдачи будет:
+ Done! сертификат и ключ для домена сгенерированы и лежат в каталоге /home/letsencrypt/letsencrypt.sh/certs/domain.tld
cert.pem privkey.pem
в принципе, это symlink-и на актуальные версии этих файлов, которые лежат в том же каталоге и в названии которых присутствует метка времени. типа cert-1453143084.pem теперь можно прописывать эти файлы в настройках http-сервера:
файл с сертификатом: /home/letsencrypt/letsencrypt.sh/certs/domain.tld/cert.pem файл с ключом: /home/letsencrypt/letsencrypt.sh/certs/domain.tld/privkey.pem обновление сертификатов производится точно так же, как и генерация: от имени пользователя letsencrypt перейдите в каталог со скриптом и запустите скрипт с тем же самым параметром — ./letsencrypt.sh -c
можно создать соответствующую cron-задачу, которая через пару месяцев (сертификаты генерируются на 90 дней) выполнит скрипт (от имени этого пользователя и в нужном каталоге) и перезапустит http-сервер

PHP вставка части изображения

Есть шаблон в PNG
И есть скриншот

Средствами PHP нужно:
а) Обрезать (изменить размер?) скриншот под размеры экрана шаблона (экран вырезан, он прозрачный).
б) Придать перспективу скриншоту.
в) Вставить скриншот на прозрачную область шаблона.
Что нужно использовать - GD, Imagick? И как вставлять скриншот - по координатам или по маске экрана шаблона?


Ответ

Я думаю, стоит использовать ImageMagick. Он умеет искажать в перспективе, по четырём точкам – что вам и нужно. И вот примеры искажений на php – вам понадобится Bilinear:
//Example 5 - Bilinear
$imagick = new \Imagick(realpath($this->control->getImagePath())); $points = array( 0, 0, 25, 25, # top left 176, 0, 126, 0, # top right 0, 135, 0, 105, # bottom right 176, 135, 176, 135 # bottum left ); $imagick->setImageBackgroundColor("#fad888"); $imagick->setImageVirtualPixelMethod(\Imagick::VIRTUALPIXELMETHOD_BACKGROUND); $imagick->distortImage(\Imagick::DISTORTION_BILINEAR, $points, true); header("Content-Type: image/jpeg"); echo $imagick;
Понадобятся 4 точки из исходного изображения – просто углы скриншота, и 4 точки, в которые они должны после искажения попасть – границы области экрана в PNG.
Ваш скрин не совсем хорош пропорциями: он квадратный, а у экрана iPad mini экран 4:3 (1024:768). Если вписывать по ширине, снизу останется пустое место. Если по высоте, край пропадёт из виду. Просто вписать – растянется в высоту.

BindingList и привязка данных

У меня есть лист в который я могу добавить\удалить какой-то объект , как сделать чтобы на это событие сразу отреагировал ListBox?


Ответ

Надо привязать ListBox к коллекции
// #r "System.Windows.Forms" using System.Windows.Forms; using System.ComponentModel;
var bl = new BindingList() { 1, 2, 3 }; new Timer { Enabled=true, Interval=1000 } // для примера каждую секунду .Tick += (s, e) => bl.AddNew(); // добавляем новые элементы в bl var f = new Form(); var lb = new ListBox() { Parent = f, Dock = DockStyle.Fill, DataSource = bl // привязка ListBox к BindingList }; f.ShowDialog();

Если надо в ListBox выводить значение свойства, то в lb надо добавить ValueMember
var lb = new ListBox() { DataSource = bl, ValueMember = "тут имя свойства"; };

Если в ListBox надо выводить изменения свойств объектов, то в объектах надо реализовать интерфейс INotifyPropertyChanged
public class Data : INotifyPropertyChanged { // требуется для уведомления о изменении значения свойств. public event PropertyChangedEventHandler PropertyChanged = delegate {}; public int Id { get; internal set; } public long Value { get { return _Value; } internal set { if (_Value != value) { _Value = value; PropertyChanged(this, new PropertyChangedEventArgs("Value")); }}} long _Value = 0; }
Работающий пример на c# тут

UPDATE
в лист добавляю число 1, а в лист бокс должна вывестись не единица, а "Число 1"
Проще всего сделать так
class Data { public int Value { get; set; } public string Text { get { return "Число " + this.Value; } } } var bl = new BindingList() { new Data { Value = 1 } }; var lb = new ListBox() { Parent = f, DataSource = bl, ValueMember="Value", DisplayMember="Text" };

запуск метода элемента listview, который на экране

нужно загружать картинку в элементы listview, но так как элементов может быть много, загружать их все сразу не очень разумно, как сделать так, чтобы метод запускался только у тех жлементов, что на экране, пробовал так:
list.setOnScrollListener(new AbsListView.OnScrollListener() { public void onScrollStateChanged(AbsListView view, int scrollState) { // Log.d(LOG_TAG, "scrollState = " + scrollState); }
@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { for(int i = firstVisibleItem; i <= visibleItemCount; i++){ element.get(i).loadCover(); } list.invalidate(); } });
но загружаются только первые 6 картинок, а дальше все


Ответ

Для подобной(Относительно. Ленивая асинхронная загрузка изображений) есть маленькая библиотека https://github.com/thest1/LazyList
Проблема вашего кода - вы считаете что visibleItemCount - общее кол-во элементов в адаптере, но это кол-во видимых элементов. Т.е. после шестого элемента вы запускаете цикл с параметром i=7;i<6.
Можно сделать так. Хотя метод onScroll и плохо работает при быстрой прокрутке.
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if(((firstVisibleItem + visibleItemCount) == totalItemCount) && totalItemCount > 0)){ loadNewData(); } list.invalidate(); }
или слегка поправить ваш код
for(int i = firstVisibleItem; i <= (firstVisibleItem+visibleItemCount)&&i<=totalItemCount; i++){ element.get(i).loadCover(); }

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

Есть таблица Persons
| ID | Name | Post | | 1 | Kolin | manager | | 2 | Emma | specialist |
Нужно создать копию таблицы - Persons_history котарая отслеживает изменений.
| ID | Name | Post | created_at | created_by | Operation | +----+-------+------------+-----------------------------+------------+-----------+ | 1 | Kolin | manager | 2015-08-06 10:04:28.6000000 | hh\Mark | Insert | | 2 | Emma | specialist | 2015-08-17 17:55:03.6600000 | hh\Mark | Update |
К примеру таблица должна выглядит так. Как можно реализовать? Как создать таблицу истории?


Ответ

Создаём таблички:
IF OBJECT_ID('Persons')IS NOT NULL DROP TABLE Persons IF OBJECT_ID('Persons_History')IS NOT NULL DROP TABLE Persons_History GO
CREATE TABLE Persons( Id INT IDENTITY(1,1), name VARCHAR(255), post VARCHAR(255) )
GO
CREATE TABLE Persons_History( Id INT, name VARCHAR(255), post VARCHAR(255), modify_at DATETIME, modify_by NVARCHAR(255), Operation VARCHAR(6) ) GO
Создание триггеров(можно обойтись и одним на самом деле)
CREATE TRIGGER Persons_History_Trigger_Insert ON Persons AFTER INSERT AS INSERT Persons_History SELECT Id, name, post, GETDATE(), SUSER_SNAME(), 'insert' FROM INSERTED GO CREATE TRIGGER Persons_History_Trigger_Update ON Persons AFTER UPDATE AS INSERT Persons_History SELECT Id, name, post, GETDATE(), SUSER_SNAME(), 'update' FROM INSERTED GO CREATE TRIGGER Persons_History_Trigger_Delete ON Persons AFTER DELETE AS INSERT Persons_History SELECT Id, name, post, GETDATE(), SUSER_SNAME(), 'delete' FROM DELETED GO
DML операции и вывод результата
INSERT Persons VALUES('Kolin', 'manager'),('Emma','specialist')
UPDATE Persons SET name='pegoopik' WHERE id=1
DELETE FROM Persons
SELECT * FROM Persons_History
Ну и результат:
Id name post modify_at modify_by Operation ----------- ---------- ---------- ----------------------- ------------------------------ --------- 2 Emma specialist 2016-01-22 12:12:44.157 ALPHA\XXX-Krasovskiy-EA insert 1 Kolin manager 2016-01-22 12:12:44.157 ALPHA\XXX-Krasovskiy-EA insert 1 pegoopik manager 2016-01-22 12:12:44.160 ALPHA\XXX-Krasovskiy-EA update 2 Emma specialist 2016-01-22 12:12:44.160 ALPHA\XXX-Krasovskiy-EA delete 1 pegoopik manager 2016-01-22 12:12:44.160 ALPHA\XXX-Krasovskiy-EA delete
Можно ещё добавить, что вместо VARCHAR(6) для поля Operation можно хранить код операции, например, в byte. 0-insert; 1-update; 2-delete. Чуть сэкономит место.

masm как сделать массив с изменяемой длиной

Возможно ли изменить длинну массива (dd) и затем записать её в eax?


Ответ

И нет, и да. Дело в том, что результат декларации dd - просто последовательность байт в бинарнике, которая статически грузится в память.
Так что менять размер тут просто нечему. dd не является командой динамического выделения памяти - она просто статически помещает в бинарник нужную последовательность байт.
Хотите выделить память - обратитесь к операционной системе и попросите. Через системный вызов.

Не работает атрибут “android:imeOptions”

В некотором layout есть EditText и если по документации от Google установить этому виджету атрибут android:imeOptions="actionSearch", то вместо стандартного значка "Enter" на клавиатуре должна появиться иконка поиска (лупа). Но когда я попробовал это реализовать на практике

иконка осталась прежней. Т.е смена иконки не работает. Попробовал реализовать смену иконки программно, написав в Activity : editText.setImeOptions(EditorInfo.IME_ACTION_SEARCH); Это, к сожалению, тоже не сработало. Более того, видимо как следствие этого, не работает и переопределенный метод для обработки нажатия по кнопке поиска:
@Override public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
Log.d("WHALETAG", "Что то собирается нажаться"); if (i == EditorInfo.IME_ACTION_SEARCH){ Toast.makeText(this, "Поиск: " + editText.getText(), Toast.LENGTH_SHORT).show(); return true; }
return false; }
От чего такое?


Ответ

Решение нашлось довольно нестандартно:
если это происходит, необходимо для EditText указать еще один атрибут android:singleLine="true"
И в результате получится:

и иконка поиска будет исправно отображаться.

Почему регулярное выражение выбрасывает исключение?

Вот задание:
Вывести на консоль все теги, которые соответствуют заданному тегу Каждый тег на новой строке, порядок должен соответствовать порядку следования в файле Количество пробелов,
,
не влияют на результат Файл не содержит тег CDATA, для всех открывающих тегов имеется отдельный закрывающий тег, одиночных тегов нету Тег может содержать вложенные теги
Вот шаблоны тэгов из задания:
text1 text1 text1
text1, text2 могут быть пустыми
Ввод такой:
string1 string2 string11
Вывод должен быть таким:
string1 string2 string11 string2
Какой регэксп для этого нужен? Вот мой тестировочный код:
public class Solution {
public static void main(String[] args) {
String testStr = "string1 string2 string11";
Pattern p = Pattern.compile("(\\<(/?[^\\>]+)\\>)"); Matcher m = p.matcher(testStr);
while(m.find()) { System.out.println(testStr.substring(m.start(), m.end())); }
} }
И ответ к нему.
(?=((?:(?1)|<(?!/span>)|[^<]+)+))
Но у меня не получается "прикрутить"
Pattern p = Pattern.compile("(?=((?:(?1)|<(?!/span>)|[^<]+)+))");
пишет вот такое:
Exception in thread "main" java.util.regex.PatternSyntaxException: Dangling meta character '?' near index 0 ?=(<(span)>(?:(?1)|<(?!/\2>)|[^<]+)+)
Подскажите как адаптировать регулярку под мою задачу?


Ответ

В вашем регулярном выражении:
(?=((?:(?1)|<(?!/span>)|[^<]+)+))
Определение группы захвата (?1) не является корректным с точки зрения синтаксиса регулярных выражений в JAVA, т.к. рекурсивные паттеры из PHP PCRE в ней не поддерживаются - ошибка выдаётся именно из-за этого

Вашу задачу необходимо решать с использованием HTML-парсера, например jsoup
String html = "string1 string2 string11"; String tag = "span";
Document document = Jsoup.parse(html);
document.select(tag).forEach((element) -> { System.out.println(element.outerHtml()); });
Этот код выводит:
string1 string2 string11 string2
Что вполне соответствует требуемому от правильного решения.

Yii2, файл вне web, скачать его

В проекте на Yii2, я загружаю через форму файлы в папку files, находящуюся в корне проекта, а не в папке web.
Как вывести ссылки на эти файлы в view, чтобы их можно было скачивать, как-то динамически?


Ответ

У меня нет под рукой ни php, ни Yii2, поэтому ограничусь подсказками, а не готовым решением из разряда "скопируй и выполни".
Вам нужен некий контролер, назовем его FilesController

class FilesController extends Controller { // ... }
Внутри него будут два action'а - actionIndex и actionDownload. Первый будет служить для показа списка файлов, а второй для непосредственной выдачи содержимого файла пользователю.
Так же нам понадобится некое свойство, которое будет содержать путь к папке с файлами. В Yii2 путь к корневой папке находится в Yii::$app->basePath. Соответственно, пишем в методе инициализации контролера:
/** * @var string */ private $path;
public function init() { $this->path = realpath(Yii::$app->basePath . '/files/'); }
В actionIndex получаем список файлов и передаём его в view:
public function actionIndex() { $files = array();
foreach (new DirectoryIterator($this->path) as $item) { array_push($files, $item->getFilename()); }
return $this->render('files', array( 'files' => $files )); }
В view вам нужно будет вывести список ссылок указывающих на actionDownload. Url для каждого файла можно получить примерно так:
Url::to(['download','name'=> $fileName]);
Ну и собственно в actionDownload отдаём файл(для $name желательно добавить валидацию, что бы пользователи не присылали всякую ересь):
public function actionDownload($name) { return Yii::$app->response->sendFile($this->path . $name); }

Сколько используется ресурсов процессора согласно выводу программы top?

Сервер работает на дистрибутиве debian gnu/linux 7. Запускаю конвертацию видеофайла через ffmpeg размером 400мб из формата avi в mp4. Команда простейшая, без дополнительных параметров:
$ ffmpeg -i pathInput -f mp4 pathOutput
Решил посмотреть использование ресурсов сервера командой top. Вот какую информацию получил по процессу ffmpeg
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 55291 admin 20 0 379m 120m 5484 S 378.5 0.2 17:08.12 ffmpeg
Если не ошибаюсь, согласно этим данным, используется 378.5% CPU.
Как это может быть? Я неправильно интерпретирую эти значения?


Ответ

число в столбце %cpu (процент использоания процессора) суммируется по всем ядрам (реальным или виртуальным) всех процессоров.
в данном случае число 378.5 говорит, скорее всего, о том, что четыре ядра используются почти на сто процентов.

кстати, у программы top есть возможность показывать (в верхней, «заголовочной» части «окна» программы) не только общую нагрузку на все ядра всех процессоров, но и на каждое ядро в отдельности. переключается этот режим нажатием кнопки 1
пример вывода по всем ядрам:
top - 18:17:10 up 11 days, 13 min, 19 users, load average: 0.11, 0.25, 0.25 Tasks: 203 total, 1 running, 202 sleeping, 0 stopped, 0 zombie %Cpu(s): 1.9 us, 0.5 sy, 0.0 ni, 95.8 id, 1.8 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 8218532 total, 3391900 used, 4826632 free, 468744 buffers KiB Swap: 2719740 total, 0 used, 2719740 free, 1168472 cached
пример вывода по каждому ядру отдельно:
top - 18:17:17 up 11 days, 13 min, 19 users, load average: 0.09, 0.24, 0.25 Tasks: 203 total, 1 running, 202 sleeping, 0 stopped, 0 zombie %Cpu0 : 1.6 us, 1.6 sy, 0.0 ni, 96.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 0.8 us, 0.8 sy, 0.0 ni, 98.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 8218532 total, 3409680 used, 4808852 free, 468744 buffers KiB Swap: 2719740 total, 0 used, 2719740 free, 1190592 cached

Как нарисовать фигуру подобную картинке

Как нарисовать подобную фигуру в xml. И стоит ли ее рисовать, или лучше использовать png (будет использоваться в качестве кнопки и будет в дальнейшем анимироваться)


Ответ

Используйте 9-patch png. Добавьте к изображению раму толщиной в один пиксель, которая будет содержать информацию для растягивания изображения и размещения на нем контента.
И измените расширение файла на имя_файла.9.png
В дальнейшем это изображение можно будет использовать в качестве фона, который будет растягиваться в нужных местах, таким же образом делаются разные облачка для диалогов и.т.д.
Преобразовать также можно с помощью png to 9-patch сервисов.

Определение порта, к которому подключено устройство

Использую библиотеку jssc для использования COM-портов в java. Такая ситуация: к компьютеру подключена arduino, и надо в коде определить, к какому порту она подключена. Как это реализовать?


Ответ

С точки зрения компьютера, Ардуина является конвертером USB->COM, обычным USB-устройством, со своими VID и PID.
Вам нужно прочитать ветку реестра, выудить оттуда VID и PID, и по ним узнать имя COM порта.
Как это делается на C++ я уволок отсюда
///

/// Compile an array of COM port names associated with given VID and PID /// /// /// /// List ComPortNames(String VID, String PID) { String pattern = String.Format("^VID_{0}.PID_{1}", VID,PID); Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase); List comports = new List(); RegistryKey rk1 = Registry.LocalMachine; RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum"); foreach (String s3 in rk2.GetSubKeyNames()) { RegistryKey rk3 = rk2.OpenSubKey(s3); foreach (String s in rk3.GetSubKeyNames()) { if (_rx.Match(s).Success) { RegistryKey rk4 = rk3.OpenSubKey(s); foreach (String s2 in rk4.GetSubKeyNames()) { RegistryKey rk5 = rk4.OpenSubKey(s2); RegistryKey rk6 = rk5.OpenSubKey("Device Parameters"); comports.Add((string)rk6.GetValue("PortName")); } } } } return comports; }
static void Main(string[] args) { List names = ComPortNames("0403", "6001"); if (names.Count > 0) { foreach (String s in SerialPort.GetPortNames()) { if (names.Contains(s)) Console.WriteLine("My Arduino port is " + s); } } else Console.WriteLine("No COM ports found"); }

CIDER ругается на nRepl после обновления пакетов в Emacs

; CIDER 0.11.0snapshot (package: 20160125.741) (Java 1.8.0_72, Clojure 1.7.0, nREPL 0.2.10) WARNING: CIDER requires nREPL 0.2.12 (or newer) to work properly WARNING: The following required nREPL ops are not supported: apropos classpath complete eldoc format-code format-edn info inspect-pop inspect-push inspect-refresh macroexpand ns-list ns-vars ns-path refresh resource stacktrace toggle-trace-var toggle-trace-ns undef Please, install (or update) cider-nrepl 0.11.0-SNAPSHOT and restart CIDER WARNING: CIDER's version (0.11.0-snapshot) does not match cider-nrepl's version (not installed). Things will break! user>

Как устранить конфликты в пакетах?
project.clj:
(defproject lesson-rpg1 "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.7.0"]] :main ^:skip-aot lesson-rpg1.core :target-path "target/%s" :profiles {:uberjar {:aot :all}})
lein deps :tree
D:\CODE\Clojure\lesson-rpg1>lein deps :tree [clojure-complete "0.2.3" :exclusions [[org.clojure/clojure]]] [org.clojure/clojure "1.7.0"] [org.clojure/tools.nrepl "0.2.10" :exclusions [[org.clojure/clojure]]] D:\CODE\Clojure\lesson-rpg1>
lein version:
D:\CODE\Clojure\lesson-rpg1>lein version Leiningen 2.5.2 on Java 1.8.0_72 Java HotSpot(TM) 64-Bit Server VM D:\CODE\Clojure\lesson-rpg1>


Ответ

Сложилась неприятная ситуация
...в самом Leiningen будет указана старая версия tools.nrepl до следующего релиза. Поэтому нужно указать версию явно в проекте или профиле (см. далее):
[org.clojure/tools.nrepl "0.2.12" :exclusions [[org.clojure/clojure]]]
...и так, чтобы при этом не приклеивалась зависимость от конкретной версии Clojure. И ещё, похоже, потребуется это:
[cider/cider-nrepl "0.11.0-SNAPSHOT"]

Что происходит
Если проект не указывает версию org.clojure/tools.nrepl явно, то используется та, что распространяется с Leiningen, в вашем случае это оказалась старая версия 0.2.10
Можно действовать любым из следующих способов:
указать её явно прямо в проекте в списке зависимостей добавить в профиль по умолчанию (~/.lein/profiles.clj)
это зависимость, поэтому подлежит записи под ключом :dependencies обновить Leiningen и получить новую встроенную версию tools.nrepl
на данный момент неактуально, ждём очередного релиза Leiningen.
Поскольку речь о совместимости проекта с вашей собственной средой разработки (а код самого проекта не зависит от этого), первый вариант плохо подходит, а второй скорее "заплатка".