Страницы

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

пятница, 7 июня 2019 г.

Как в C передать в функцию переменное количество аргументов?

Есть функция, которая завершает программу, выполняя занесение отладочной информации в файл лога:
void crash(const char *const _fstr, ...) { if ( (_fstr != NULL) && (strlen(_fstr) > 0) ) { FILE *f = fopen(CRASH_LOG_FILE_NAME, "a"); fprintf(f, _fstr, ???); fclose(f); }
abort(); }
Я хочу сделать, чтобы в функцию crash() передавалась строка формата и какое-то количество аргументов. Ситуации бывают разные. При некоторых крашах в файл желательно заносить не только строку с описанием проблемы, но еще и ряд кодов, например GetLastError() и WSAGetLastError()
Как это сделать?


Ответ

Вам нужно использовать функцию vfprintf, а передавать ей аргумент типа va_list, который получаете в своей функции примерно как
void crash(const char *const _fstr, ...) { va_list ap; va_start(ap, _fstr);
... vfprintf(f,_fstr,ap);
... va_end(ap);

Получить список параметров, python3.x argparse

Запускаю фаил в командной строке с такими аргументами:
python test.py -f a.jpg b.jpg -t png
как получить список файлов a.jpg b.jpg ? использую библиотеку argparse


Ответ

Что бы получить аргументы как список нужно использовать nargs='+'. В документации описано как можно интерпретировать количество параметров используя nargs https://docs.python.org/2/library/argparse.html#nargs
import argparse
parser = argparse.ArgumentParser(description='description') parser.add_argument('-l', '--list', nargs='+')
if __name__ == '__main__': args = parser.parse_args() print(args)
При вызове скрипта с параметрами получим следующий вывод
python test.py -l q a 1 Namespace(list=['q', 'a', '1'])

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

Всем привет!
Столкнулся с проблемой верскти не совсем обычного слайдера диапазона значений. До сегодняшнего дня думал, что умею неплохо верстать, оказалось это не совсем так :)
Друзья подскажите, как мне заверстать такой элемент. Пробовал через transform: skewY с псевдоэлементом , но это не лучший способ,- результат не совсем тот.
В общем, друзья, подтолкните меня на правильную мысль, или дайте ссылочку на пример такого элемента Спасибо!


Ответ

Перетаскивание ползунка уж как-нибудь сами прикрутите
$('[type=number]').on('input',function(){ $('.range__value').css('background-size', this.value+'% 100%'); $('.range__btn').css('left',this.value+'%'); }) *{ box-sizing:border-box; } body{ margin:0; padding:15px; } .range{ position:relative; height:20px; } .range__inner{ height:100%; overflow:hidden; position:relative; } .range__value{ height:100%; background:linear-gradient(to right,red,green),#ddd; background-size:50% 100%; background-repeat:no-repeat; transform:rotate(-1.3deg); transform-origin:right center; } .range__btn{ display:inline-block; border:1px solid #bbb; width:20px; height:20px; background-color:#fff; border-radius:0 30px 30px 30px; position:absolute; top:calc(100% + 5px); left:50%; transform:translateX(-50%) rotate(45deg); cursor:pointer; }


Распарсить XML с xmltype() с обработкой исключений в запросе

Есть запрос:
select nvl(extractvalue(xmltype(p.src_doc, 871), '//*:' || pd.name), extractvalue(xmltype(p.src_doc, 871), '*/*[local-name()="AdditionalData"][*[local-name()="Name"]="' || pd.name || '"][1]/*[local-name()="Value"]')) as elm_value, pd.guid as param_guid, p.guid as pmnt_guid from payments p join services s on p.srv_guid = s.guid join parameters_definitions pd on s.guid = pd.srv_guid left outer join pmnt_elements_values elm on p.guid = elm.pmnt_guid and pd.guid = elm.param_guid where elm.guid is null and p.src_doc is not null;
В принципе корректно парсит XML в clob, но иногда может возникнуть исключение:
ORA-31011: сбой разбора XML ORA-19202: Возникла ошибка при обработке XML LPX-00601: Invalid token in: '//*: PAYMENTTYPE ' 31011. 00000 - "XML parsing failed" *Cause: XML parser returned an error while trying to parse the document. *Action: Check if the document to be parsed is valid.
Проблема в том, что некоторые XML корректны, некоторые нет, таблица довольно объемна. Единого примера XML тоже дать не могу, так как все XML-документы корректны в рамках своей схемы, но по понятным причинам имеют разные значения в нодах, разные неймспейсы и атрибуты в некоторых нодах.
Можно ли как-то обойти/проигнорировать/обработать исключения разбора XML? Можно ли хотя бы как-то получить понимание где конкретно и на чем разваливается парсер?
Версия: Oracle Database 11g Enterprise Edition.


Ответ

Надо обернуть всю логику по разбору XML в функцию, которая обработает исключения и запишет полную информацию об ошибках, например, в таблицу. Как-то так:
create table parseErrors (guid raw (16), errm varchar2 (4000), created timestamp);
create or replace function myXmlParser (docGuid raw, doc clob) return varchar2 is procedure saveParseError (guid raw, errm varchar2) is pragma autonomous_transaction; begin insert into parseErrors values (guid, errm, systimestamp); commit; end ; begin -- **здесь необходимая логика, в которой может возникнуть ошибка** return xmlType (doc).getStringVal (); exception when others then saveParseError (docGuid, sqlerrm||chr(10)||sys.dbms_utility.format_error_backtrace()); return 'errorneous'; end myXmlParser; /
Выборка для теста (вместо sys_guid() должна быть колонка с GUID из запроса):
select myXmlParser (sys_guid(), 'some data') from dual union all select myXmlParser (sys_guid(), 'illegal XML syntax') from dual ;
выведет:
RESULT ------------------------ some data errorneous
Kакие были ошибки:
set lines 999 col errm for a40 wrapp select * from parseErrors;
GUID ERRM CREATED -------------------------------- ---------------------------------------- ----------------------------- 7106268B980F02D3E0530A01A8C04FBB ORA-31011: XML parsing failed 2018-07-15 12:32:41,204757000 ORA-06512: at "SYS.XMLTYPE", line 272 ORA-06512: at "DB.MYXMLPARSER", line 10

PS В вопросе мало информации по локализации причины ошибки, но думаю ссылки на похожие топики тут и тут будут полезны.

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

У меня есть строка
$path = '/user/5';
Мне нужно извлечь число 5 из нее, я могу проверить ее регулярным выражением:
preg_match('/\/user\/[0-9]/', $path, $matches)
Но в данном случае $matches будет равен $path (var_dump $matches):
array(1) { [0]=> string(7) "/user/5" }
Как максимально быстро извлечь 5?


Ответ

В своем выражении, вы не объявляете группировку ([0-9]+), нужно брать в круглые скобки, попробуйте так:
$path = '/user/5';
preg_match('~/user/([0-9]+)~', $path, $matches);
echo $matches[1];

Rust: преобразование обобщённого типа в конкретный

Собственно код:
extern crate num_traits;
pub trait DigitCount { fn decimal_digit_count(&self) -> usize; }
impl > DigitCount for T { fn decimal_digit_count (&self) -> usize { if self.is_zero() { 1 } else { self.into().abs().log10().trunc() as usize + 1 } } }
Метод decimal_digit_count должен вызываться для любого целого значения и возвращать количество десятичных разрядов в нём:
println!("{}", 123u64.decimal_digit_count());
Вопрос: как правильно записать преобразование T → f64 для последующего вызова методов abs, log10, trunc? В текущем виде компилятор требует аннотацию типа для into(), но если её подставить (into::()), то говорит, что ожидается 0 параметров типов.


Ответ

У самого метода и правда нет типового параметра, потому что он есть у типажа:
pub trait Into { fn into(self) -> T; }
Первый вариант исправления - просто явно указать через промежуточную переменную какой тип мы в итоге хотим получить:
let f: f64 = self.into(); f.abs().log10().trunc() as usize + 1
(playpen)
Второй вариант - использовать UFCS форму вызова метода с явным обозначением T у типажа:
Into::::into(self).abs().log10().trunc() as usize + 1
(playpen)
Метод decimal_digit_count должен вызываться для любого целого значения и возвращать количество десятичных разрядов в нём
На всякий случай еще добавлю что преобразование в f64 реализовано не для всех целых типов. Такое преобразование обязано всегда заканчиваться успехом, что невозможно, например, для u64 или i128 из-за невозможности вместить весь диапазон значений.

Oracle job queue

Есть job, который запускает процедуру с входящими параметрами через программу. Как запустить job вовремя ее выполнения чтобы она стала в очередь и начала отрабатывать после завершения первой, но уже с другими параметрами?
job запускаю след образом
dbms_scheduler.set_job_argument_value('GPIMS.JOB_UPD_GP_ADDR_MAPP',1,IN_GP_ID); dbms_scheduler.set_job_argument_value('GPIMS.JOB_UPD_GP_ADDR_MAPP',2,to_char(P_GP_STATUS_DATE)); dbms_scheduler.enable('GPIMS.JOB_UPD_GP_ADDR_MAPP');
Создание job
begin dbms_scheduler.create_job('GPIMS.JOB_UPD_GP_ADDR_MAPP', program_name => 'GPIMS.PROGRAM_UPD_GP_ADDR_MAPP', auto_drop => FALSE); end;
Создание программы
begin sys.dbms_scheduler.create_program(program_name => 'GPIMS.PROGRAM_UPD_GP_ADDR_MAPP', program_type => 'STORED_PROCEDURE', program_action => 'GPIMS.PKG_GLOBAL_PROBLEM.UPD_GP_ADDR_MAPP', number_of_arguments => 3, enabled => false, comments => ''); sys.dbms_scheduler.define_program_argument(program_name => 'GPIMS.PROGRAM_UPD_GP_ADDR_MAPP', argument_position => 1, argument_name => 'IN_GP_ID', argument_type => 'VARCHAR2', default_value => ''); sys.dbms_scheduler.define_program_argument(program_name => 'GPIMS.PROGRAM_UPD_GP_ADDR_MAPP', argument_position => 2, argument_name => 'P_GP_STATUS_DATE', argument_type => 'DATE', default_value => ''); sys.dbms_scheduler.define_program_argument(program_name => 'GPIMS.PROGRAM_UPD_GP_ADDR_MAPP', argument_position => 3, argument_name => 'OUT_MSG', argument_type => 'VARCHAR2', default_value => ''); sys.dbms_scheduler.enable(name => 'GPIMS.PROGRAM_UPD_GP_ADDR_MAPP'); end;


Ответ

Так нельзя делать. Невозможно запустить once Job, который уже выполняется. Для этого есть цепочки (job chains), но передать к каждому звену цепочки свои параметры также не представляется возможным.
Можно передать каждому звену мета данные, например: job_name, job_subname, как формальные параметры. Они будут замещены актуальными значениями для выполняемой задачи и соответственно звена задачи. Далее определить эти же данные как ключ в таблице для параметров.
Подготовим схему:
create table myJobInfo (beg timestamp, end timestamp, info varchar2 (256)); create or replace type myJobArgs as object ( jobName varchar2 (32), jobStepName varchar2 (32), argChar varchar2 (64), argDate date); / create table myJobArgsTab of myJobArgs; insert into myJobArgsTab select myJobArgs ( 'myJob', 'chainStep'||rownum, 'arg char '||rownum, date'2018-07-01'+(rownum-1)) from xmlTable ('1 to 3');
Создадим программу и цепочку выполненения, которая будет запускать эту программу в каждом звене:
begin sys.dbms_scheduler.create_program ( program_name=>'myJobProg', program_type=>'stored_procedure', program_action=>'myJobProc', number_of_arguments=>2, enabled=>false, comments=>'test job') ; dbms_scheduler.define_metadata_argument ( program_name=>'myJobProg', metadata_attribute=>'job_name', argument_position=>1 ); dbms_scheduler.define_metadata_argument ( program_name=>'myJobProg', metadata_attribute=>'job_subname', argument_position=>2 ); sys.dbms_scheduler.enable ('myJobProg'); -- create chain/steps dbms_scheduler.create_chain ('myJobChain'); dbms_scheduler.define_chain_step ('myJobChain', 'chainStep1', 'myJobProg'); dbms_scheduler.define_chain_step ('myJobChain', 'chainStep2', 'myJobProg'); dbms_scheduler.define_chain_step ('myJobChain', 'chainStep3', 'myJobProg'); -- rules dbms_scheduler.define_chain_rule ('myJobChain', condition=>'true', action=>'start chainStep1'); dbms_scheduler.define_chain_rule ('myJobChain', condition=>'chainStep1 completed', action=>'start chainStep2'); dbms_scheduler.define_chain_rule ('myJobChain', condition=>'chainStep2 completed', action=>'start chainStep3'); dbms_scheduler.define_chain_rule ('myJobChain', condition=>'chainStep3 completed', action=>'end'); dbms_scheduler.enable ('myJobChain'); end; /
Тест процедура:
create or replace procedure myJobProc (jobName varchar2, jobStepName varchar2) is rowid_ rowid; args myJobArgs; begin begin select value (t) into args from myJobargsTab t where upper (t.jobName) = myJobProc.jobName and upper (t.jobStepName) = myJobProc.jobStepName for update ; exception when others then dbms_output.put_line ('ERROR: '||jobName||'.'||JobStepName||': sqlerrm:'||sqlerrm); end; insert into myJobInfo (beg, info) values ( systimestamp, jobName||'.'||JobStepName||': args='||args.argChar||'/'||to_char (args.argDate,'yyyy-mm-dd')) returning rowid into rowid_ ; sys.dbms_lock.sleep (3); update myJobInfo set end=systimestamp where rowid=rowid_; end; /
Запустим всю цепочку и посмотрим, что получилось:
exec dbms_scheduler.run_chain (chain_name=>'myJobChain', start_steps=>null, job_name=>'myJob');
select * from myJobInfo order by beg desc;
BEG END INFO ------------ ------------ ---------------------------------------------------------------- 10:52:24.246 10:52:27.246 MYJOB.CHAINSTEP3: args=arg char 3/2018-07-03 10:52:21.202 10:52:24.202 MYJOB.CHAINSTEP2: args=arg char 2/2018-07-02 10:52:18.154 10:52:21.154 MYJOB.CHAINSTEP1: args=arg char 1/2018-07-01
Для дальнейшей информации читаем оф. документацию тут и тут

В чем разнице между двумя модулями в Python?

Какая разница между двумя модулями в Python?
Для примера я взял pickle но есть и другие модули подобного вида, что лучше и когда применять, дайте совет


Ответ

Модуль pickle сразу импортирует _pickle , если есть такая возможность. _pickle это c оптимизированная версия pickle
Из исходников модуля pickle
# Use the faster _pickle if possible try: from _pickle import ( PickleError, PicklingError, UnpicklingError, Pickler, Unpickler, dump, dumps, load, loads ) except ImportError: Pickler, Unpickler = _Pickler, _Unpickler dump, dumps, load, loads = _dump, _dumps, _load, _loads
В Python 2 _pickle была также известна как cPickle
Источник

Почему добавляются непонятные символы в БД при вводе русских букв (кириллицы) в phpMyAdmin?

На странице, в которой ввожу данные, кодировка текста "< meta charset="utf-8>". Ввел строку "Главная"

Вывод на другой странице выглядит так:

В БД кодировка - utf8_general_ci, а запись этих строк выглядит вот так:


Ответ

Скрипт, который пишет в БД, не установлена кодировка обмена с mysql. В итоге скрипт пишет в БД в кодировке по умолчанию (скорее всего Latin). Поскольку и читает он в этой же кодировке, то на сайте все отображается как надо, а вот в phpMyAdmin, настроенном на utf8, вы видите "кракозябры".
В скрипте, после соединения с БД надо выполнить запрос
SET NAMES utf8
чтобы установить нужную кодировку обмена с БД

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

Tickers.All();
class Tickers : Eloquent {
}
class Eloquent { public static void All() { Console.WriteLine("Класс из которого вызывали меня"); } }
Хочу в классе Eloquent получить название класса Tickers.
Подскажите пожалуйста)


Ответ

Статические методы привязаны к определенному типу и не наследуются. В вашем случае Tickers.All() на самом деле скомпилится в Eloquent.All(), поэтому в рантайме не будет даже упоминания о Tickers
Чтобы реализовать вашу задумку, нужно немного подшаманить:
Вариант 1
class Tickers : Eloquent { public static new void All() => Eloquent.All(); }
class Eloquent { public static void All() { var stacktrace = new StackTrace(); var prevframe = stacktrace.GetFrame(1); var method = prevframe.GetMethod();
Console.WriteLine($"Вызывающий класс: {method.ReflectedType.Name}"); } }
Либо, как прокомментировал @Grundy, посмотреть еще один способ. Если коротко, то:
Вариант 2
class Tickers : Eloquent { }
class Eloquent where T: Eloquent { public static void All() { Console.WriteLine($"Вызывающий класс: {typeof(T).Name}"); } }

Сортировка внутри JSON (sql, Postgres)


Есть таблица в Postgres, как на картинке. Формат данных в before и after - JSON. Необходимо сравнить данные из before и after внутри zone_limitation. Основная проблема заключается в том, что данные могут иметь разную сортировку, а при разной сортировке такие JSON-ячейки будут восприниматься, как разные, даже если будут иметь одинаковые цифры внутри.


Ответ

в postgresql есть операторы @> и <@ для jsonb
эти операторы проверяют структурного вхождение одного jsonb в другой (не взирая на последовательность ключей), т.о. если вам нужно проверить эквивалентность, то можно использовать комбинацию этих операторов, например:
with t as ( select "id", "before"#>'{"custom_targeting","include","zone_limitation"}' as "b", "after"#>'{"custom_targeting","include","zone_limitation"}' as "a" from "test" ) select t.id "id", (t.a @> t.b and t.a <@ t.b)::boolean "Checker" from t order by 1
*данный ответ базируется на dbfiddle от 2SRTVF, см. оригинальный ответ: https://ru.stackoverflow.com/a/858064/265453

Почему json_decode на данном объекте может не работать?

Ниже представлен HTTP-запрос. Мне нужно извлечь из него данные - массив с ключами cells и distance.
curl http://localhost:80/problem2.php -X POST -H Content-Type:application/json --data-binary "{'cells': [4,8,11,18,19], 'distance': 2}"
Но ничего не выходит, так как данные считываются не верно. Ниже - считывание данных.
$data = json_decode(file_get_contents('php://input'));
Известно, что file_get_contents('php://input') точно получает данный массив. Почему json_decode() может не рабоать?


Ответ

JSON строго регламентирует использование двойных кавычек:
--data-binary '{"cells": [4,8,11,18,19], "distance": 2}'
var_dump(json_decode('{"cells": [4,8,11,18,19], "distance": 2}'));
Fiddle

Как обратиться к методу объекта из колбэка в JS?

Вот у меня есть код:
class BaseInput{ constructor(value){ this.makeButtonVisible = null; this.makeButtonVisible = function(){ alert(1234); }; this.makeButtonInvisible = null;
this._input = document.createElement('input'); this._input.type = 'text'; this._input.value = value; this._input.dataset.value = value;
this._input.oninput = function(){ if (this.value != this.dataset.value) BaseInput.makeButtonVisible(); else alert(321); }
document.querySelector('.container').appendChild(this._input); } }
в this._input.oninput я добавляю функцию, которая должна обратиться к методам makeButtonVisible или makeButtonInvisible этого объекта


Ответ

this._input.dataset.value = value; this._input.logic = this;
this._input.oninput = function(e) { if (this.value != this.dataset.value) this.logic.makeButtonVisible(); else alert(321); };
или
this._input.dataset.value = value;
this._input.oninput = (e) => { if (this._input.value != this._input.dataset.value) this.makeButtonVisible(); else alert(321); };
или
this._input.dataset.value = value;
this._input.oninput = (function(e) { if (this._input.value != this._input.dataset.value) this.makeButtonVisible(); else alert(321); }).bind(this);

ProgressBar при переходе между страницами сайта.

Есть страница A и страница Б. Как при плохом качестве подключения пользователю показывать ProgressBar. Подчеркиваю что это событие должно происходить именно при ПЛОХОМ качестве подключения к сети ! Спасибо!!!


Ответ

А как вы собираетесь узнать, что у него плохое качество? Вообще вас спасет Loader, он плюс минус для такого и нужен. Чем быстрее страница будет грузиться, тем меньше по времени он будет, ну и плюс современно.
P.S. Как вариант, плохое качество можно задетектить с помощью JS смотреть за сколько секунд страница A грузится, если больше определенного времени - ставим куку (временную), и тогда при запросе страницы Б, смотрим наличие этой куки, если есть, то выкидываем лоадер.

Линукс дистрибутив с минимальным набором утилит для запуска java команд

Подскажите линукс дистрибутив (или что удалить лишнего), чтобы было возможно запускать только java команды? Мне не нужен ни GUI, ни apt-get, ничего такого.
Как я понял, нужно оставить лишь папку bin, в которой сидит bash и его друзья. я прав?


Ответ

Соберите свой, если есть часов 40-60 свободного времени. Linux From Scratch например дает пошаговые инструкцию.
На сайте Oracle есть исходники, можете скрафтить сами.
Минимальные дистры:
http://www.linuxfromscratch.org/ https://www.archlinux.org/ http://puppylinux.com/
Исходники OpenJDK
http://openjdk.java.net/
Я обычно ставлю тарбол от Oracle, там все в одном архиве - целевой дистр Ubuntu 16.04: гоняется 2 кастомных приложения, сами приложения больше, чем весь дистр.

Вывод XML на консоль - отсутствует заголовок xml файла C#

Создал XML файл с помощью класса XDocument. Вывожу готовую Xml в Консоль, но не вижу там xml заголовка в начале файла. Если его сохранить на диск, то заголовок присутствует. Почему так происходит? И как можно его туда добавить?
XDocument xdoc = new XDocument(
new XDeclaration("1.0", "Windows-1251","yes"), new XElement("Product", new XElement ("prequest", new XElement("req", new XElement("AddressReq", new XElement ("street","Горького"), new XElement ("houseNumber","1"), new XElement("apartment", "38"), new XElement("city", "Магадан"), new XElement("postal", "685000"), new XElement("addressType", "1")), new XElement("AddressReq", new XElement("street", "Горького"), new XElement("houseNumber", "1"), new XElement("apartment", "38"), new XElement("city", "Магадан"), new XElement("postal", "685000"), new XElement("addressType", "1")), new XElement("IdReq", new XElement("idNum", "273"), new XElement("idType","21"), new XElement("seriesNumber", "64"), new XElement("issueCountry", "г. Магадан"), new XElement("issueDate", "2006-03-18"), new XElement("issueAuthority", "ОВД") ), new XElement("IdReq", new XElement("idNum", "1"), new XElement("idType", "32") ), new XElement("InquiryReq", new XElement("ConsentReq", new XElement("consentFlag", "Y"), new XElement("consentDate", "2016-01-20"), new XElement("consentExpireDate", "2021-10-21"), new XElement("consentPurpose", "4"), new XElement("otherConsentPurpose", "Job pre-screening"), new XElement("reportUser", "DG Human Resources Incorporated"), new XElement("liability", "Y") ), new XElement("inqPurpose", "01"), new XElement("inqAmount", "10000"), new XElement("currencyCode", "usd") ), new XElement("PersonReq", new XElement("name1", "К"), new XElement("first", "Г"), new XElement("paternal", "Г"), new XElement("gender", "1"), new XElement("birthDt", "1900-00-00"), new XElement("placeOfBirth", "Москва") ), new XElement("RequestorReq", new XElement("MemberCode", "V"), new XElement("UserID", "V"), new XElement("Password", "1") ), new XElement("RefReq",
new XElement("product", "CHST") ), new XElement("IOType","B2B"), new XElement("OutputFormat", "xml"), new XElement("lang", "ru") )) ))
Вывод в консоль :
xdoc.Save("C:\\file.xml"); //В сохраненном файле xml есть заголовок byte[] byteArray = Encoding.GetEncoding(1251).GetBytes(xdoc.ToString()); BinaryWriter write = new BinaryWriter(File.Open("C:\\file.dat", FileMode.OpenOrCreate)); write.Write(byteArray); //а вот в бинарном файле нет.
Console.WriteLine(xdoc); //Если вывести сам xdoc то тут тоже нет заголовка. Console.ReadKey();


Ответ

Метод ToString у класса XDocument не выводит заголовок xml. Поэтому его нет в бинарном файле.
Когда вы пишете Console.WriteLine(xdoc) - тут тоже вызывается ToString
Хотите получить заголовок в консоли, используйте
xdoc.Save(Console.Out);
Не пугайтесь, что encoding выведется другой. Кодировка будет такой, какую поддерживает консоль.

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


1) Подскажите, как реализовать такую диаграмму, которая бы рабоатла вместе с календарем. Как нарисовать это все.
2) Внизу есть список из radioButton и поверх них зеленная линия вертикальная. Как сделать эту линию в RecyclerView?


Ответ

Пожалуй начнем с простой, второй части:
Нижняя часть экрана - это RecyclerView. RadioButton находиться всегда в одном месте в Item/ячейке/поле этого RecyclerView. Тогда, поверх RecyclerView, вы проводите прямую: FrameLayout шириной в 1 пиксель, нужного цвета таким образом, чтобы он оказался поверх RadioButtons. Высоту RecyclerView ставите по контенту, чтобы прямая не уходила в никуда (либо приделываете эту маленькую палочку непосредственно к RadioButton в самом Item, получается эдакая прямоугольная башенка)
Верхняя часть сложнее. Так или иначе придется копаться в канвасе и писать собственный фрагмент с диаграммой. Вы можете попробовать найти схожую либу с открытым исходным кодом и "позваимствовать" код оттуда (android arsenal вам в помощь). График вы оформляете в виде фрагмента, где месяцы - это TabLayout + ViewPager
Как-то так.

Сохранение лучшей модели

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


Ответ

Вы можете воспользоваться callbacks для сохранения лучшей модели и для ранней остановки (чтобы избежать бесполезных вычислений и ускорить время обучения модели):
from keras.callbacks import EarlyStopping, ModelCheckpoint
early_stop = EarlyStopping(monitor='val_acc', min_delta=0.0001, patience=5, verbose=1, mode='auto') chkpt = ModelCheckpoint(model_filename, monitor='val_loss', verbose=1, save_best_only=True, mode='auto') callbacks = [early_stop, chkpt]
hist = model.fit(x_train, y_train, batch_size=Batch_size, epochs=Epochs, validation_data=(x_val, y_val), callbacks=callbacks)

Неверный возврат ссылки на элемент, в чем проблема?

При вводе, например, десятого элемента и попытке сменить его значение, меняет 3ий элемент, при попытке сменить первый элемент может сменить 4ый, выходит какой-то рандом, в чем проблема?
int &change(int i); int vals[10];
int main(){
int ch, newval; cout << "Enter your array.." << endl; for(int j = 0;j<10; j++) cin >> vals[j];
cout << "
" <<"Choose element which you want to change.. "; cin >> ch; cout << "Enter the new value for this element.. "; cin >> newval; newval = change(vals[ch-1]); cout << endl; for (int i=0; i<10; i++) cout << vals[i] <<" "; // вывод массива
return 0; }
int &change(int k){
return vals[k]; }


Ответ

Передавайте в функцию индекс элемента, а не значение из массива:
change(ch-1) = newval;

Возврат функции при соблюдения условия

Допустим есть функция, которая возвращает случайную цифру:
function getNumber() { $Numbers = '1234567890'; $NumbersSize = strlen($Numbers) - 1; $getNumber = $Numbers[rand(0, $NumbersSize)]; return $getNumber; }
Как заставить ее возвращать только нужную мне цифру, с помощью цикла?


Ответ

$getNumber = $Numbers[rand(0, $NumbersSize)]; while($getNumber != $nuzhnajaCifra) $getNumber = $Numbers[rand(0, $NumbersSize)]; return $getNumber;
Но не проще ли без цикла:
return $nuzhnajaCifra;

Не активный скроллбар при открытой модалке (не скрыть а именно не активный), как?

Вот столкнулся с такой проблемой что необходимо сделать скроллбар именно не активным т.к. при скрытии скроллбара сайт разъезжается. И в целом не вижу смысла делать всем элементам (боди и прочим стики элементам падинги).
Вот идеальный пример того что хочу это на сайте apple.com если кликнуть по поиску, то скроллбар как бы остаётся и из него только пропадает сам бегунок и получается аналогичный эффект как при overflow:hidden, но при этом сайт не дергается на эти самые 10/13/16 пикселей.
Попытался посмотреть как у них это реализовано, но понять не смог... Возможно js или еще как-то... В гугле искал ничего толкового не смог найти, все советы просто скрыть скроллбар и всё.


Ответ

добавьте в css:
html { overflow-y: scroll; }

Почему findFragmentById возвращает null?

Объясните пожалуйста, почему getSupportFragmentManager().findFragmentById(R.id.fragment_container) возвращает null если в классе SingleFragmentActivity он добавляется в FragmentManager?


public class MyFragment extends Fragment { }

public abstract class SingleFragmentActivity extends AppCompatActivity { FragmentManager fm= getSupportFragmentManager(); protected abstract Fragment createFragment(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment); Fragment fragment = fm.findFragmentById(R.id.fragment_container); if (fragment == null) { fragment = createFragment(); fm.beginTransaction() .add(R.id.fragment_container, fragment) .commit(); } } }

public class MyActivity extends SingleFragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Возвращает null Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container); } @Override protected Fragment createFragment() { return new MyFragment(); } }


Ответ

Вызов commit() не выполняет транзакцию немедленно, а ставит в очередь UI-потока. Поэтому следующий за ним вызов findFragmentById выполняется раньше, чем фрагмент будет добавлен. Вместо этого можно завершить транзакцию синхронным методом commitNow() - тогда всё выполнится по порядку.

Принцип работы Array.prototype.concat()

Для скрипта в Adobe Photoshop, есть диалоговое окно с элементами выбора и управления:
var dlg = new Window('dialog{text: "Выбор размеров", bounds: [' + fBounds(150,200,370,150) + '], \ panel_s: Panel{text: "Стандартные:", bounds: [' + fBounds(5,5,203,85) + '], \ checkbox_16: Checkbox{bounds: [' + fBounds(5,13,55,14) + '], text: "16 x 16"}, \ checkbox_24: Checkbox{bounds: [' + fBounds(5,33,55,14) + '], text: "24 x 24"}, \ checkbox_32: Checkbox{bounds: [' + fBounds(5,53,55,14) + '], text: "32 x 32"}, \ checkbox_48: Checkbox{bounds: [' + fBounds(67,13,55,14) + '], text: "48 x 48"}, \ checkbox_64: Checkbox{bounds: [' + fBounds(67,33,55,14) + '], text: "64 x 64"}, \ checkbox_96: Checkbox{bounds: [' + fBounds(67,53,55,14) + '], text: "96 x 96"}, \ checkbox_128: Checkbox{bounds: [' + fBounds(129,13,65,14) + '], text: "128 x 128"}, \ checkbox_256: Checkbox{bounds: [' + fBounds(129,33,65,14) + '], text: "256 x 256"}, \ checkbox_512: Checkbox{bounds: [' + fBounds(129,53,65,14) + '], text: "512 x 512"} \ }, \ panel_o: Panel{text: "Другие:", bounds: [' + fBounds(206,5,69,64) + '],\ checkbox_19: Checkbox{bounds: [' + fBounds(5,13,55,14) + '], text: "19 x 19"}, \ checkbox_38: Checkbox{bounds: [' + fBounds(5,33,55,14) + '], text: "38 x 38"} \ }, \ panel_u: Panel{text: "Свои:", bounds: [' + fBounds(273,5,92,85) + '],\ checkbox_u1: Checkbox{bounds: [' + fBounds(5,13,14,14) + ']}, \ static_u1: StaticText{bounds: [' + fBounds(21,13,31,14) + '], text: ". . . x", justify: "right"}, \ edittext_u1: EditText{bounds: [' + fBounds(53,11,30,19) + '], text: ". . .", properties: {multiline: false}}, \ \ checkbox_u2: Checkbox{bounds: [' + fBounds(5,33,14,14) + ']}, \ static_u2: StaticText{bounds: [' + fBounds(21,33,31,14) + '], text: ". . . x", justify: "right"}, \ edittext_u2: EditText{bounds: [' + fBounds(53,31,30,19) + '], text: ". . .", properties: {multiline: false}}, \ \ checkbox_u3: Checkbox{bounds: [' + fBounds(5,53,14,14) + ']}, \ static_u3: StaticText{bounds: [' + fBounds(21,53,31,14) + '], text: ". . . x", justify: "right"}, \ edittext_u3: EditText{bounds: [' + fBounds(53,51,30,19) + '], text: ". . .", properties: {multiline: false}} \ }, \ button_all: Button{bounds: [' + fBounds(208,70,64,19) + '], text: "Все"}, \ static_save: StaticText{bounds: [' + fBounds(5,99,75,14) + '], text: "Сохранить в:"}, \ drop_save: DropDownList{bounds: [' + fBounds(78,95,287,23) + '], properties: {items: ["папку рядом с исходным файлом", "-", "Выбрать папку..."]}, helpTip:"Ooops!!!"}, \ progress_save: Progressbar{bounds: [' + fBounds(0,0,370,4) + '], value:50}, \ button_run: Button{bounds: [' + fBounds(4,122,70,22) + '], text: "Создать"} \ };' );
// -- Выбор всех значений
dlg.show();
Есть обработчик кнопки, для выбора всех чекбоксов:
// -- Выбор всех значений dlg.button_all.addEventListener('click', function() {
alert(dlg.panel_s.children + '
' + dlg.panel_s.children.length); // Коллекция (9 элементов) и количество (9) отображаются верно
alert(dlg.panel_o.children + '
' + dlg.panel_o.children.length); // Коллекция (2 элемента) и количество (2) отображаются верно
// Объединяем обе коллекции и три отдельных элемента var aPanel = [].concat( dlg.panel_s.children, dlg.panel_o.children, dlg.panel_u.checkbox_u1, dlg.panel_u.checkbox_u2, dlg.panel_u.checkbox_u3 );
alert(aPanel + '
' + aPanel.length); // Массив отображается верно (14 элементов), но количество не совпадает (5) ! });
Из комментариев в коде обработчика видно, где возникает проблема, и вопрос следующий...Метод Array.prototype.concat(), согласно документации, должен объединять массивы, раскрывая их до первого уровня вложенности. Собственно, так и происходит, если верить последнему всплывающему окну (см. код обработчика) - там отображаются все элементы в порядке добавления.Но, при обращении к aPanel[0], возвращается не первый элемент (checkbox_16), а вся коллекция dlg.panel_s.children . Соответственно при этом, длина массива aPanel составляет 5, а добраться до нужного элемента можно только указав вложенность в коллекции, т.е. aPanel[0][0] .Это баг или хитрая логика? И как правильно объединить массивы с помощью concat() ?


Ответ

Поправочка
Действительно, согласно справке MDN
Метод concat создаёт новый массив, состоящий из элементов в объекте, на котором он был вызван, за которыми по порядку следуют, для каждого аргумента, все его элементы (если аргумент является массивом), либо сам аргумент (если он массивом не является)
Только вот про первый уровень вложенности, как видите, тут ни слова.Вот Вам наглядный пример: let x = [].concat(1, 2, [3, 4], [5, 6, [7, 8]]); console.log(x); // Выведем полученный массив console.log(x.length); // Длина равняется не 8, как если бы все раскрывалось // до первого уровня вложенности, а 7! console.log(x[6]); // 6-ой элемент является массивом
Однако это не отменяет Вашей проблемы, так как в Вашем случае, если бы элементы dlg.{foo}.children были массивами, то их разворачивание все равно бы произошло

Так в чем же дело?
Не буду Вас томить и наконец скажу, в чем же проблема. Еще раз обратите внимание на строчку:
если аргумент является массивом
К чему я клоню? Указанные Вами элементы не являются массивами! Да, они являются коллекциями и подобны массивам, но все же спецификация строга.
Давайте посмотрим, как метод concat ведет себя с объектом arguments, который, как и Ваши элементы, является по сути коллекцией, но не массивом:
function test() { console.log(Array.isArray(arguments)); // false return [].concat(arguments, arguments); } console.log(test(1, 2, 3).toString()); // [object Arguments], [object Arguments]
Как видите, concat не стал разбираться, коллекция ли это или обычный объект. Для него важно лишь то, что данная конструкция не является массивом
P.S. - чтобы иметь возможность проверять, является ли объект массивом или нет, советую посмотреть в сторону функции Array.isArray()

Что делать?
Лучшим вариантом будет не полениться и все добавить руками:
var aPanel = []; for (let i = 0; i < dlg.panel_s.children.length; i++) aPanel.push(dlg.panel_s.children[i]); for (let i = 0; i < dlg.panel_o.children.length; i++) aPanel.push(dlg.panel_o.children[i]); aPanel.push(dlg.panel_u.checkbox_u1, dlg.panel_u.checkbox_u2, dlg.panel_u.checkbox_u3);

Другой вариант
Можете определить свой метод на уровне прототипа, который как раз и будет разворачивать и массивы, и коллекции до первого уровня:
Array.prototype.fullConcat = function() { const exclude = ["string"]; // Пусть строка и является коллекцией, но мы хотим считать ее цельным объектом function getElements(item) { // Рекурсивно получим все элементы внутри заданного (если таковые есть) let result = []; if (item.length === undefined || exclude.includes(typeof item)) result.push(item); else { for (let i = 0; i < item.length; i++) { let add = getElements(item[i]); for (let j = 0; j < add.length; j++) result.push(add[j]); } } return result; } let concated = []; for (let i = 0; i < arguments.length; i++) { // Начнем объединение let item = arguments[i]; if (item.length === undefined || exclude.includes(typeof item)) concated.push(item); else { for (let i = 0; i < item.length; i++) { let add = getElements(item[i]); for (let j = 0; j < add.length; j++) concated.push(add[j]); } } } // Не забудем и про контекст this, который может оказаться совсем не пустым return this.length == 0 ? concated : [].fullConcat(this, concated); }; function testArguments() { return [].fullConcat(arguments, arguments); } // Проверим, как метод расправится со вложенностью console.log([1, 2, 3].fullConcat([4], [5, 6, [7, 8, [9, 10]]], "hello", "world")); // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "hello", "world" // Проверим, как метод расправится с коллекцией в лице arguments console.log(testArguments(1, 2, 3, [4, 5])); // 1, 2, 3, 4, 5, 1, 2, 3, 4, 5

UPD:
Большое спасибо @Grundy за то, что обратил мое внимание на следующий момент:
Давайте же глянем не справку MDN, а на спецификацию ECMAScript. Обратим внимание на строчки:
Repeat, while items is not empty a. Remove the first element from items and let E be the value of the element. b. Let spreadable be ? IsConcatSpreadable(E) c. If spreadable is true, then
// copy items from within the object d. Else:
// copy the object
Или на русском:
Повторять, пока items не пуст a. Удалить первый элемент из items, присвоить E значение элемента. b. Присвоить spreadable значение IsConcatSpreadable (E). c. Если spreadable является true, тогда
// копировать элементы изнутри объекта d. Иначе:
// копировать сам объект
То есть за то, будет ли элемент добавлен к результирующему массиву в явном виде, или же он будет предварительно развернут как коллекция, отвечает результат выполнения некой функции IsConcatSpreadable(O). Давайте же взглянем, что это и с чем ее едят:
If Type(O) is not Object, return false Let spreadable be ? Get(O, @@isConcatSpreadable) If spreadable is not undefined, return ToBoolean(spreadable) Return ? IsArray(O).
Или на русском:
Если тип O не Object, вернуть false. Присвоить spreadable значение свойства @@isConcatSpreadable объекта O. Если spreadable не undefined, вернуть ToBoolean (spreadable). Вернуть IsArray(O).
То есть проверка на то, является ли объект массивом, идет в самую последнюю очередь. До этого проверяется, обладает ли объект свойством Symbol.isConcatSpreadable, и если он таковым обладает, то его булевое значение и будет показателем того, будет ли он раскрываться при concat.
Давайте теперь применим это на практике:
// Создадим собственную коллекцию var userCollection = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; // Убедимся, что она не является массивом console.log(Array.isArray(userCollection)); // false // Посмотрим, что вернет нам concat console.log([].concat(userCollection, userCollection)); // Array [ Object(3), Object(3) ] // Теперь маленькая хитрость: // Установим внутреннее свойство, отвечающее // за результат IsConcatSpreadable(O), равным true userCollection[Symbol.isConcatSpreadable] = true; // Посмотрим, что теперь вернет нам concat console.log([].concat(userCollection, userCollection)); // Array [ "a", "b", "c", "a", "b", "c" ] // Или же сразу создадим коллекцию с указанным свойством: // Создадим собственную коллекцию var userCollection_1 = { 0: 'a', 1: 'b', 2: 'c', length: 3, [Symbol.isConcatSpreadable]: true }; // Посмотрим, что вернет нам concat console.log([].concat(userCollection_1, userCollection_1)); // Array [ "a", "b", "c", "a", "b", "c" ]
Работает как часы. Давайте для чистоты эксперимента проверим это на существующем перечисляемом типе. Вспомним опять же про наш arguments
// arguments не указан, как spreadable function nonSpreadable() { return [].concat(arguments, arguments); } // arguments указан, как spreadable function spreadable() { arguments[Symbol.isConcatSpreadable] = true; return [].concat(arguments, arguments); } // Какой же массив вернется при объединении 2-х arguments? console.log(nonSpreadable(1, 2)); // Array [ Arguments, Arguments ] // А теперь?) console.log(spreadable(1, 2)); // Array [ 1, 2, 1, 2 ] console.log(spreadable(1, 2, 3)); // Array [ 1, 2, 3, 1, 2, 3 ]
Как видите, нам удалось с помощью concat объединить внутренние значения arguments в массив
Для очистки совести напомню: лезть таким вот образом во внутренние свойства объекта, изменяя логику его работы, - неправильно и кощунственно!
Почему? Давайте представим ситуацию: Вы видите массив. Как он должен вести себя с методом concat? Правильно, согласно уже не раз указанной справке он обязан раскрыться при объединении! А что если кто-то с полученным Вами массивом поигрался следующим образом: // Создадим обычные массивы var arr_0 = [1, 2]; var arr_1 = [3, 4]; // Убедимся, что это именно массивы, а не что-либо еще console.log(Array.isArray(arr_0)); // true console.log(Array.isArray(arr_1)); // true // Объединим их var arr_2 = [].concat(arr_0, arr_1); console.log(arr_2); // Array [ 1, 2, 3, 4 ] console.log(arr_2.length); // 4, как и полагается // А теперь сделаем парочку богопротивных действий arr_0[Symbol.isConcatSpreadable] = arr_1[Symbol.isConcatSpreadable] = false; // Объединим их снова var arr_3 = [].concat(arr_0, arr_1); console.log(arr_3); // Array [ Array(2), Array(2) ] console.log(arr_3.length); // 2, что-то пошло не так)
Только что мы изменили поведение стандартного типа, что очень и очень неправильно! Так что старайтесь избегать таких вот подходов!
Все, совесть очищена, так что можем злоупотреблять дальше :)

Еще один вариант решения Вашей проблемы:
На основе манипулирования результатом исполнения IsConcatSpreadable(O) Вашу задачу можно решить таким вот образом:
// Колдуем над isConcatSpreadable: dlg.panel_s.children[Symbol.isConcatSpreadable] = dlg.panel_0.children[Symbol.isConcatSpreadable] = true;
// Объединяем обе коллекции и три отдельных элемента var aPanel = [].concat( dlg.panel_s.children, dlg.panel_o.children, dlg.panel_u.checkbox_u1, dlg.panel_u.checkbox_u2, dlg.panel_u.checkbox_u3 );
И живой пример для наглядности:
// Сформируем свои коллекции var userCollection_0 = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; var userCollection_1 = { 0: 'd', 1: 'e', 2: 'f', 3: 'g', length: 4 }; // Колдуем над isConcatSpreadable userCollection_0[Symbol.isConcatSpreadable] = userCollection_1[Symbol.isConcatSpreadable] = true; // Объединяем обе коллекции и три отдельных элемента var aPanel = [].concat( userCollection_0, userCollection_1, 'h', 'i', 'j' ); // Посмотрим, что внутри console.log(aPanel); // Array [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" ] // Убедимся, что длина также совпадает console.log(aPanel.length); // 10 из 10)

Надеюсь, мой ответ помог Вам в разрешении проблемы! Удачи в Ваших начинаниях!

Можно ли над методом рест-контроллера ставить аннотацию @Transactional?

Можно ли над методом рест-контроллера ставить аннотацию @Transactional? Будут ли проблемы, если одновременно по этому URL одновременно будут пытаться получить данные несколько клиентов?


Ответ

Нельзя, однозначно и бесповоротно. Будут проблемы связанные с обработкой транзакций.

Здесь я укажу некоторые ссылки:
Слой использования @Transactional анотации.
Что лучше всего с @Transactional, вы должны положить его, если у вас есть доступ к базе данных. См. «Понимание реализации декларативной транзакции Spring Framework»
вы просто аннотируете свои классы аннотацией @Transactional, добавляете в свою конфигурацию строку (``), а затем ожидаете, что вы поймете, как все это работает.
Какой слой использовать для транзакций и сессии Hibernate
Лучше всего использовать управление транзакциями Spring. Аннотации @Transactional для использования транзакций. На заводе-изготовителе используется LocalSessionFactoryBean. Все бобы управляются весной, поэтому у вас нет забот.
Spring Hibernate - различие между CrudRepository и SessionFactory
Просто вы можете найти описание этих аннотаций на сайте docs Spring. В ближайшее время, чтобы ответить на ваши вопросы, разница между ними заключается в том, что они используются для разных целей.
@Transactional используется для демаркации кода, участвующего в транзакции. Он помещается на классы и методы.
@Repository используется для определения Spring-компонента, поддерживающего транзакции, его также можно использовать в DI. Они могут использоваться как в одном классе.

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

void getFiles(const string& inpath, string outpath) { string mask = inpath + "\\*"; WIN32_FIND_DATA FindFileData; HANDLE hf; hf = FindFirstFile(mask.c_str(), &FindFileData);
ofstream output; output.open(outpath + "\\data.txt", ios_base::app);
if (hf != INVALID_HANDLE_VALUE) { do { if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (strcmp(FindFileData.cFileName, ".") == 0 || strcmp(FindFileData.cFileName, "..") == 0) continue; getFiles(inpath + "\\" + FindFileData.cFileName, outpath); } else output << inpath << "\\" << FindFileData.cFileName << endl;
} while (FindNextFile(hf, &FindFileData) != 0); FindClose(hf); }
output.close(); }
Есть такая функция, которая ищет файлы в выбранном каталоге и его подкаталогах, а потом записывает пути к файлам в data.txt. А как мне сделать так, чтобы эта функция искала только файлы с определенным расширением, например, .xml?


Ответ

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

Почта попадает в спам, как изменить?

Добавил обычную функцию отправки письма:
$subject = "Test mail";
$message = "Hello! This is a simple email message.";
$from = "registration@MYDOMAIN.RU";
$headers = "From: Info
";
mail($to,$subject,$message,$headers);
echo "Mail Sent.";
Решил проверить на спам через mail-tester. Он показывает 0/10(даже -2). Самая основная Ошибка, это: Адрес возврата : webmaster@example.com. Хотя я установил FROM. Ошибка точно не в коде отправки почты. И так же пишет [SPF] example.com не позволяет Вашему серверу myserverIP использовать webmaster@example.com Те же самые ошибки наблюдаю, если отправляю на любой почтовый сервер письмо. Например на mail.ru. Потом захожу в сведения письма и вижу снова несовпадения. Как будто я отправляю почту от имени другого домена. Хотя я зарегистрировал адрес почты.
Как еще подтвердить, что мой сервер, домен и почта одно целое?
Установлен centos на vds. Стоит ispManager. Настроил на домене все необходимые txt, CNAME, mx записи с yandex Добавил через pdd.yandex.ru домен и подтвердил его. Создал там почту. Добавил все необходимые spf, DKIM подписи
РЕШЕНИЕ Необходимо установить опцию sendmail_path = /usr/sbin/sendmail -t -i -f mail@domain.com в php.ini


Ответ

ISPManager использует для PHP тот E-Mail, который прописан для сайта в его настройках в качестве адреса вебмастера. Это делается путём установки параметра PHP sendmail_path в конфигурационных файлах Apache, добавляя в секцию строку вида php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@example.com". Можете попробовать сменить в панели адрес на ваш настоящий. Этот параметр относится к PHP_INI_SYSTEM, так что изменить его можно лишь в системном php.ini или в конфигурационном файле Apache. Также не забудьте про SPF, DKIM и DMARC записи в DNS.

Как правильно понимать приватные свойства в ООП?

Куда сохраняются приватные свойства созданного объекта? Например у нас есть такой код:
function User() { var firstName, surname; this.setFirstName = function(firstNameUser) { firstName = firstNameUser; } this.setSurname = function(surnameUser) { surname = surnameUser; } this.getFullName = function() { return surname + ' ' + firstName; } } var user1 = new User(); user1.setFirstName('Phillip'); user1.setSurname('Moore'); console.log(user1) console.log(window.surname)
Мы создаем приватные свойства firstName и surname, но после создания нового объекта через конструктор, этих свойств нет в этом объекте. И в глобальной области видимости этих свойств тоже нет, куда они тогда сохраняются?


Ответ

Они хранятся в замыкании. Вот более просто пример этого механизма
function setSecret(secret) { const mySecret = `My secret: ${secret}`;
return function getSecret() { return mySecret; } }
const secret1 = setSecret('secret 1'); const secret2 = setSecret('secret 2');
secret1(); // secret 1 secret2(); // secret 2
В данном случае, при каждом вызове функции setSecret, создается локальная область видимости ( об А ), где хранится одна переменная mySecret. В обычном случае после выполнения функции, об А бы уничтожилась и переменная пропала, НО мы возвращаем функцию, которая имеет доступ к созданной об А, поэтому об А сохраняется.
В вашем случае механизм тот же: функция возвращает объект, у которого есть методы, использующие область видимости этой функции.

Аналог innerHTML для lxml

Как получить всё содержимое внутри HTML-тега в lxml, но без самого тега?


Ответ

Встроенного метода вроде бы нет, но нетрудно написать свой.
Проблема в том, что простой текст в lxml не является самостоятельным элементом (в отличие от Text Node в браузерах), поэтому нужно не забыть добавить text в начале.
from html import escape # Доступно с Python 3.2 import lxml.html
def inner_html(elem): # Текст в самом начале внутри тега # (не забываем про экранирование!) result = [escape(elem.text or '')]
# Все элементы-потомки for child in elem.iterchildren(): result.append(lxml.html.tostring(child, encoding='unicode')) # Текст в конце тега принадлежит последнему элементу-потомку (tail) # и добавится автоматически
# Собираем результат в одну строку return ''.join(result)

# В примере подставим <br> чтобы проверить экранирование >>> node = lxml.html.fragment_fromstring( '

Тек<br>ст1

Тек<br>ст2

Текст3
Текст4
' )
>>> lxml.html.tostring(node, encoding='unicode') '
Тек<br>ст1

Тек<br>ст2

Текст3
Текст4
'
>>> inner_html(node) 'Тек<br>ст1

Тек<br>ст2

Текст3
Текст4'

Немогу Вывести Элемент Массива (RedBeanPHP)

Есть Код:
$find = R::findAll('task','NAME LIKE ?', ['%'.$q.'%']); if($find){ // Если Массив не Пустой foreach($find as $res){ echo $res['NAME']; } }
var_dump($res); object(RedBeanPHP\OODBBean)#15 (10) { ["properties":protected]=> array(11) { ["ID"]=> string(1) "1" ["NAME"]=> string(127) "Написать 4 положительных комментария в Instagram'e и пролайкать эти 4 поста" ["DESCR"]=> string(224) "Приветствую я начинающий Блогер, веду свой блог в Instagram'e По скольку сейчас развелось очень много недо блогеров, пропиар... " ["AUTHOR"]=> string(24) "Пользователь" ["CATEGORY"]=> string(10) "Клики" ["PRICE"]=> string(4) "7500" ["WATCHS"]=> string(2) "16" ["RATING"]=> string(1) "2" ["COMPLETS"]=> string(2) "11" ["NOT_COMPLETS"]=> string(1) "2" ["CREATE_DATE"]=> string(19) "2018-06-14 09:20:06" } ["__info":protected]=> array(5) { ["type"]=> string(4) "task" ["sys.id"]=> string(2) "id" ["sys.orig"]=> array(11)
Проблема вот в чем: Я пытаюсь произвести поиск по средством Библиотеки RedBeanPHP методом findAll() все хорошо, поиск сработал но проблема в том что когда я пытаюсь вывыести Элемент массива по Его Ключу(в моем случае это NAME), Ничего не Выводится...


Ответ

Проблема решилась. Просто прошелся 2 раза циклом foreach и все.
foreach ($find as $res){ $res = (array) $res; foreach($res as $r){ $r = (array) $r; echo $r['NAME']; }

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

Есть датафрейм df. Есть фича feat имеющая три категории cat1, cat2, и немногочисленная Unknown.
Я хочу избавиться от Unknown, раскидав ее по cat1 и cat2 так, чтобы она разлетелась по ним пропорционально их доле в датасете. То есть, если изначально было 45% cat1, 40% cat2 и 5% Unknown, то нужно, чтобы Unknown разлетелась в между cat1 и сat2 в соотношении 9/8.
В документации и блогах ничего подобного не нашел.


Ответ

Исходный DF:
In [67]: %paste df = pd.DataFrame({'feat':np.random.choice(['cat1','cat2','Unknown'], size=100, p=[0.45,0.40,0.15])}) ## -- End pasted text --
In [68]: df.feat.value_counts() Out[68]: cat1 49 cat2 36 Unknown 15 Name: feat, dtype: int64
Сначала найдем соотношение между cat1 и cat2
In [69]: pct = df.feat.value_counts() / len(df)
In [70]: ratio = pct.loc[['cat1','cat2']].min() / pct.loc[['cat1','cat2']].max()
In [71]: pct Out[71]: cat1 0.49 cat2 0.36 Unknown 0.15 Name: feat, dtype: float64
In [72]: ratio Out[72]: 0.7346938775510204
теперь заменим строки с Unknown с таким же соотношением:
In [74]: df.loc[df['feat']=='Unknown', 'feat'] = \ ...: np.random.choice([pct[['cat1','cat2']].idxmax(), pct[['cat1','cat2']].idxmin()], ...: size=df['feat'].eq('Unknown').sum(), ...: p=[ratio, 1-ratio]) ...: ...:
In [75]: df.feat.value_counts() Out[75]: cat1 62 cat2 38 Name: feat, dtype: int64
проверка соотношения после замены значений:
In [76]: pct.loc[['cat1','cat2']].min() / pct.loc[['cat1','cat2']].max() Out[76]: 0.7346938775510204

С помощью python загрузить в поисковик все строки excel

У меня есть excel файл с 1000 строками, в каждой набор символов из 10 символов. Мне нужно каждый из них вставить поочередно в поиск, например, яндекса. Если выдаваемых результатов более одного - как то отметить эту строку, которую поисковик нашел. (потом я уже в ручную поиск повторю с нужной строкой) По одному результату будет в каждой строке, а я ищу когда 2 и более.


Ответ

Можно написать функцию, возвращающую число результатов поиска.
Пример:
import re import requests from bs4 import BeautifulSoup
def get_search_results_no(search_str): r = requests.get('http://www.google.com/search', params={'q':f'{search_str}'} ) if not r.ok: r.raise_for_status() soup = BeautifulSoup(r.text, 'lxml') n = re.sub('\D', '', re.sub('[^\d]*\s(\d.*\d)\s[^\d]*', r'\1', soup.find('div',{'id':'resultStats'}).text)) if n == '': return 0 return int(n)
Использование:
In [149]: get_search_results_no('MaxU') Out[149]: 1050000
In [150]: get_search_results_no('Кирилл Вишняков') Out[150]: 983000

Проблема с кодировками

Имеется утилита, которая запускает батники, которые в свою очередь собирают инфу с помощью утилиты wmic и потом с них форматирует отчет на рабочий стол.
Программа в общем-то ничего сложного не делает, обычная работа с файлами и текстом, если упростить, но проблема в том, что при чтении файла (в файле точно не UTF-8, word определил кодировку, как Юникод) поэтому геморрой с обработкой информации, с этим я в общем-то справился, вот только на ноутах она выдает дичь, где используется кириллица.
К слову к примеру если в строку я записываю кириллицу сам, то всё ок. Проблема только с файлом. Вот 1 из методов.
void networkAdapterGet() { StringBuilder result = new StringBuilder(); try(BufferedReader reader = new BufferedReader(new FileReader(NETWORK_ADAPTER_INFO_PATH)); BufferedWriter writer = new BufferedWriter(new FileWriter(TEMP_RESULT_FILE_PATH, true))) { line = reader.readLine(); while (line != null){ if (line.length() > 1){ line = trimSpaces(line); line = networkAdapterProcessing(line); if (!line.equals("")){ result.append(line); result.append(lineSeparator); } } line = reader.readLine(); } writer.write("Сетевые устройства:"); writer.write(lineSeparator); writer.write(result.toString()); writer.write(lineSeparator); writer.write(lineSeparator); } catch (IOException e) { e.printStackTrace(); } }
Скорее всего зря повелся наFileReader/Writer и думаю основная проблема, как раз таки в Reader'е. Пошаманил с кодировками на открытии и получил фигу, упало как раз таки из-за несовпадения кодировок, можно конечно перебрать вариантов там пара всего, но хотелось бы узнать можно ли как-то это дело исправить. Это пока единственный мешающий/раздражающий баг на данном этапе разработки утилитки.


Ответ

Нужно писать в той кодировке, которая читается клиентом. Чтобы указать кодировку надо заменить FileWriter на
new OutputStreamWriter(new FileOutputStream(TEMP_RESULT_FILE_PATH), StandardCharsets.UTF_8);
если кодировка UTF_8 не подходит, то можно попробовать KOI-8 или CP1251, или другая кодировка, которая поддерживает кирилицу, например CP866

Добавление зависимости androidx

Файл build.gradle выглядит следующим образом:
apply plugin: 'com.android.application'
android { compileSdkVersion 27 defaultConfig { applicationId "com.example.recyclerviewexample" minSdkVersion 14 targetSdkVersion 27 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.0.0-beta01' implementation 'androidx.recyclerview:recyclerview:1.0.0-beta01' }
Но в результате сборки ошибки:
Information:Gradle tasks [:app:generateDebugSources, :app:generateDebugAndroidTestSources, :app:mockableAndroidJar] C:\Users\Xu\.gradle\caches\transforms-1\files-1.1\appcompat-1.0.0-beta01.aar\45f296cd7466b0137ad2b0b5868320be
es\values-v28\values-v28.xml Error:(9, 5) error: resource android:attr/dialogCornerRadius not found. C:\Users\Xu\.gradle\caches\transforms-1\files-1.1\appcompat-1.0.0-beta01.aar\45f296cd7466b0137ad2b0b5868320be
es\values\values.xml Error:(1304, 5) error: resource android:attr/fontVariationSettings not found. Error:(1304, 5) error: resource android:attr/ttcIndex not found. D:\Android Projects\RecyclerViewExample\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values-v28\values-v28.xml Error:(11) error: resource android:attr/dialogCornerRadius not found. Error:(7) resource android:attr/dialogCornerRadius not found. Error:(11) resource android:attr/dialogCornerRadius not found. D:\Android Projects\RecyclerViewExample\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values\values.xml Error:(231) resource android:attr/fontVariationSettings not found. Error:(231) resource android:attr/ttcIndex not found. Error:failed linking references. Error:java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details Error:java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details Error:com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details Error:Execution failed for task ':app:processDebugResources'. > Failed to execute aapt Information:BUILD FAILED in 7s Information:13 errors Information:0 warnings Information:See complete output in console
При этом, если блок dependencies выглядит так:
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' }
то сборка проходит успешно. Как добавить зависимость androidx в проект? Версия Android Studio - 3.0.1.


Ответ

Согласно доке
New Project If you create a new project using the androidx-packaged dependencies (as opposed to refactoring an existing project with the Android Studio tool), your new project needs to target API level 28, and you will need to add the following lines to your gradle.properties file: android.useAndroidX=true android.enableJetifier=true
требуется выставить targetSdkVersion как минимум 28 и добавить явное разрешение на использование либ из androidx пакета в файле gradle.properties
android.useAndroidX=true android.enableJetifier=true

Вернуть часть строки кроме

Всем добрый день! Как правильно составить регулярку, пробовал, но не получается то, что нужно. Есть много текста вида
"rwrwerw rewrwr http://www.site1.com rewrwrw rewrewrwe needword rewrewrewrwe fdsfasfafdsa http://www.site2.com fdsafsafdsafsaf rewrewrew rewrewrewrwe fdsfasfafdsa http://www.site3.com fdsafsafdsafsaf rewrewrew"
Как можно разбить текст разделителем по слову "http://www.site.com" регуляркой с сохранением содержимого регулярки. Или найти/вернуть куски текста "http://www.site.com fdsfsaf fdsfsaf" включающие http://www.site.com в начале, но исключающие следующий http://www.site.com. Следующий http://www.site.com будет со своим последующим текстом. Перепробовал кучу вариантов, но что-то не получается. Такой вариант вроде подходит
~((?:http|https)://.?)(?=[\s]+).?(?=(?:http|https))~is
Но preg_match_all возвращает подстроки с site1 и site2, а блок текста с site3 не возвращает


Ответ

$str = 'rwrwerw rewrwr http://www.site1.com rewrwrw rewrewrwe needword rewrewrewrwe fdsfasfafdsa http://www.site2.com fdsafsafdsafsaf rewrewrew rewrewrewrwe fdsfasfafdsa http://www.site3.com fdsafsafdsafsaf rewrewrew';
$patt = '~https?://.+?(?=https?|$)~'; preg_match_all($patt, $str, $arr);
var_dump($arr);
Результат:
array (size=1) 0 => array (size=3) 0 => string 'http://www.site1.com rewrwrw rewrewrwe needword rewrewrewrwe fdsfasfafdsa ' (length=74) 1 => string 'http://www.site2.com fdsafsafdsafsaf rewrewrew rewrewrewrwe fdsfasfafdsa ' (length=73) 2 => string 'http://www.site3.com fdsafsafdsafsaf rewrewrew' (length=46)

Извлечь строку с помощью регулярных выражений

Есть строка r, из которой надо достать только ФИО человека с помощью регулярных выражений. Максимум что у меня вышло это получить '=Иванов Иван Иванович,'.
Как можно дополнить выражение, чтобы получить ФИО без лишних знаков?
import re r = 'CN=Иванов Иван Иванович,OU=0072,OU=007,OU=Users,OU=Departments,DC=contoso,DC=com,DC=ua' result = re.search(r'=\D+,',r) print(result)


Ответ

text = 'CN=Иванов Иван Иванович,OU=0072,OU=007,OU=Users,OU=Departments,DC=contoso,DC=com,DC=ua'
import re result = re.search(r'CN=(.+?),', text) print(result) print(result.group(1)) # 'Иванов Иван Иванович'

У того текста очень простой формат, можно сгенерировать словарь:
Поддержка ключей для нескольких значений:
from collections import defaultdict key_by_values = defaultdict(list)
for x in text.split(','): k, v = x.split('=') key_by_values[k].append(v)
print(key_by_values['CN']) # ['Иванов Иван Иванович'] print(key_by_values['OU']) # ['0072', '007', 'Users', 'Departments'] Ключ для одного значения:
# В одну строку: key_by_value = dict(x.split('=') for x in text.split(','))
# Или более привычно: key_by_value = dict()
for x in text.split(','): k, v = x.split('=') key_by_value[k] = v
print(key_by_value['CN']) # 'Иванов Иван Иванович' print(key_by_value['OU']) # 'Departments'

Что означает статус WONTFIX в багтрекере?

В bitbucket.org увидел у некоторых issue статус wontfix. Что это за статус?


Ответ

WONTFIX - The problem described is a bug which will never be fixed
(взято с https://en.opensuse.org/Bug_Status_WONTFIX)
Это статус для ошибок, которые признаны ошибками, но которые не будут исправляться, в виду различных причин (к примеру, излишней сложности исправления, нецелесообразности и т.п.)

Почему в php рефлексия показывает что интерфейс это абстрактный класс?

Можете, пожалуйста, подсказать почему в php 5.6.30 данный код:
interface IInterface { public function someMethod(); public function anotherMethod(); } function classData( ReflectionClass $class ) { $details = ""; $name = $class->getName();
if ( $class->isInterface() ) { $details .= "$name -- это интерфейс
"; }
if ( $class->isAbstract() ) { $details .= "$name -- это абстрактный класс
"; } return $details; }
$class_info = new ReflectionClass('IInterface'); echo classData($class_info);
выводит следующий результат:
IInterface -- это интерфейс IInterface -- это абстрактный класс
Т.е. почему интерфейс определяется как абстрактный класс?
Если удалить методы из интерфейса, то отобразится:
IInterface -- это интерфейс

Интересный факт: hhvm лишён этого недостатка


Ответ

Существует 2 типа «абстрактности» в php:
explicit - класс, явно определённый, как abstract. implicit - класс/интерфейс, содержащий абстрактные методы.
Проверить на explicit абстрактность можно так:
if ($class->getModifiers() & ReflectionClass::IS_EXPLICIT_ABSTRACT) { // Перед нами абстрактный класс }
Демонстрация

Добавить исключение в регулярное выражение

Есть задача изменять значение поля input (автоматически делать заглавную букву в начале нового предложения - "чтоб как в word" ) почти получилось при помощи следующей функции
function(){ inputPos = this.selectionStart; this.value = this.value.replace(/((?:(?:^|[.?!]\s)\s*))(.)/g, function(m, tail, ch){return tail + ch.toUpperCase()}) this.selectionStart = inputPos; this.selectionEnd = inputPos; }
подскажите, как добавить исключение в регулярку, чтобы игнорировались слова длиной в 1 символ (т.к. т.ч. т.е.) и после них буква в слове оставалась строчной
Пример ввода:
"любой текст. меняется по onclick в инпуте! текст произвольный, но нужно игнорировать сокращения т.е. слова длиной в один символ заканчивающиеся точкой т.к. такова идея. очень лень шифт нажимать... ну не дичь ли? вот так"
Пример Вывода:
"Любой текст. Меняется по onclick в инпуте! Текст произвольный, но нужно игнорировать сокращения т.е. слова длиной в один символ заканчивающиеся точкой т.к. такова идея. Очень лень шифт нажимать... Ну не дичь ли? Вот так"


Ответ

Я пока лучше ничего не придумал, но вроде работает:
/(?<=(^|([а-я]{2,})[!?.]{1,}\s))./
Подробности:
(?<= - начало предпросматриваемой незахватывающей группы
(^|([а-я]{2,}) - условие, по которому мы избавляемся от таких сокращенных слов т.е., т.к. и прочих таких сокращений, где стоит меньше 2 символов а-я [!?.]{1,} - свои спец. символ, по которым осуществляем поиск в пределах от 1+ ) - конец предпросматриваемой группы - выбираем первую нужную нам букву
var string = 'любой текст. меняется по onclick в инпуте!!! ' + 'текст произвольный... нужно игнорировать сокращения т.е. слова ' + 'длиной в один символ заканчивающиеся точкой т.к. такова идея. ' + 'очень лень шифт нажимать... ну не дичь ли!? вот так'; var value = string.replace(/(?<=(^|([а-я]{2,})[!?.]{1,}\s))./gi, function(ch) { return ch.toUpperCase(); }); console.log(value);

Удалить пустой массив из многомерного массива

Есть массив такого вида:
Array ( [0] => Array ( [date] => 07.08.2018 [name] => Название 1 [desc] => Описание 1. )
[1] => Array ( [date] => 07.08.2018 [name] => Название 2 [desc] => Описание 2. )
)
Т.е. В массиве массивы в тремя ключами.
Как удалять массивы, в которых не заполнен один или более ключей? Т.е. оставлять только те поля, в которых всё заполнено?
Например, при таких ситуациях:
Array ( [0] => Array ( [date] => 07.08.2018 [name] => Название 1 [desc] => Описание 1. )
[1] => Array ( [date] => 07.08.2018 [name] => Описание 2 [desc] => Описание 2. )
[2] => Array ( [date] => [name] => [desc] => )
)
или
Array ( [0] => Array ( [date] => 07.08.2018 [name] => Название 1 [desc] => Описание 1. )
[1] => Array ( [date] => 07.08.2018 [name] => Название 2 [desc] => Описание 2. )
[2] => Array ( [date] => [name] => Описание 3 [desc] => )
)
Удалить массив с ключом [2]


Ответ

$arr = [ [ 'date' => '07.08.2018', 'name' => 'Название 1', 'desc' => 'Описание 1.' ], [ 'date' => '07.08.2018', 'name' => 'Название 1', 'desc' => 'Описание 1.' ], [ 'date' => '', 'name' => 'Название 1', 'desc' => '.' ] ];
foreach ($arr as $idx => $subarray) { foreach ($subarray as $name => $item) { if ($item == null) unset($arr[$idx]); } }
print_r($arr);

Laravel подстановка маршрута

Как в Laravel использовать подстановку маршрута. Например:$route['category/(:any)/page/(:num)'] = '/category/page/$1/$2';


Ответ

Примерно как-то так:
Route::any('category/{id}/page/{page}', 'CategoryController@show')->where('page', '[0-9]+');
И сам контроллер:
namespace App\Http\Controllers;
use App\User; use App\Http\Controllers\Controller;
class CategoryController extends Controller { public function show($id, $page) { return; } }

Что быстрее: скопировать файлы или разархивировать?

Наверное туповатый вопрос, поскольку по логике разархивация должна быть дольше, тем более если есть сжатие. Но всё же, вдруг не всё так просто как кажется.
Что будет быстрее, скопировать папку с файлами в 1гб, или же разархивировать архив с точно такими же файлами без сжатия.


Ответ

Думаю все дело в I/O записи, что обычно ниже чем чтения
Тесты
~$ du -sh test/ 5.2G test/
Прямое копирование:
~$ time cp -R tmp/ test/ real 0m34.953s user 0m0.084s sys 0m5.110s
Сжатие, копирование, распаковка:
~$ time { tar cf tmp.tar tmp && mv tmp.tar test/ && tar xf test/tmp.tar -C test/; } real 1m1.619s user 0m0.563s sys 0m12.964s
Копирование уже сжатого каталога:
~$ time cp tmp.tar test/ real 0m26.251s user 0m0.028s sys 0m4.557s
Посчитаем колчиество чтения-записи
Для архива:
~$ strace cp tmp.tar test/ 2>&1 | grep -c "read\|write" 55259 ~$ strace cp tmp.tar test/ 2>&1 | grep -c "write" 27623
Для каталога:
~$ strace cp -R tmp test/ 2>&1 | grep -c "read\|write" 70955 ~$ strace cp -R tmp test/ 2>&1 | grep -c "write" 32455
В итоге разница между количеством записей для каталога и пакета вышла 4832, что при копирование на медленный носитель, может значительно увеличить время ожидания.
При хорошем CPU имеет смысл паковать все предварительно перед копированием. 00

Посмотреть код без инструкций препроцессора

Есть ли программа, которая бы как компилятор начинала собирать проект и останавливалась после этапа препроцессора? Чтобы оставался чистый код, как если бы его писали без препроцессорных команд. Хотя было бы неплохо, чтобы в итоге он бы разделял фрагменты кода по именам заголовочных файлов.


Ответ

Как минимум в gcc (и, соответственно, в его производных, типа minGW) препроцессор — это отдельная программа, которая назвается cpp:
cpp -o yourfile.c.preprocessed yourfile.c
Поверьте, один раз прочитав его вывод, вы поймёте, почему фраза "бойтесь своих желаний, они могут сбыться" не лишена смысла :)

Для чего xmlns:app и xmlns:tools ? И обязательны ли они?

Видел как некоторые разработчики удаляют эти строки из layout файла, хотя они появляются изначально по умолчанию. Так что, стоит ли удалять их, раз они не выпоняют важной роли в проекте ?


Ответ

xmlns:app нужен для обозначения кастомных свойст View. xmlns:tools - позволяет среде разработки (в нашем случае, Android Studio) правильно отобразить компоненты для просмотра в режиме дизайна.
Подробнее про tools
Подробнее про app

Изменение кастомного макета для Spinner'a после его создания

Можно ли как-нибудь изменить кастомный макет для Spinner'a после его создания? Например, у меня есть Spinner, макет которого состоит из TextView и ImageView




наполнение его выглядит так:
Spinner spinner = findViewById(R.id.spinner_sorting); ArrayAdapter spinnerAdapter = new ArrayAdapter(this, R.layout.spinner_row, R.id.tv_sorting, getResources().getStringArray(R.array.sorting_array)); spinner.setAdapter(spinnerAdapter);
и в итоге Spinner выглядит следующим образом:

А мне хотелось бы изменить каждую вторую ImageView в этом Spinnere. Как это можно сделать?


Ответ

Создала кастомный адаптер для Spinner-a:
public class SortingSpinnerAdapter extends ArrayAdapter { private LayoutInflater inflater; private Context context; private String[] data;
public SortingSpinnerAdapter(@NonNull Context context, int resource, int textViewResourceId, String[] data) { super(context, resource, textViewResourceId, data); inflater = LayoutInflater.from(context); this.context = context; this.data = data; }
@Override public View getView(int position, View convertView, ViewGroup parent) { return createView(position, convertView, parent); }
@Override public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { return createView(position, convertView, parent); }
private View createView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.spinner_row, parent, false); holder = new ViewHolder(); holder.textView = convertView.findViewById(R.id.tv_sorting); holder.imageView = convertView.findViewById(R.id.iv_arrow); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } onBindViewHolder(holder, position); return convertView; }
private void onBindViewHolder(ViewHolder holder, int pos) { holder.textView.setText(data[pos]); if (pos % 2 == 0) { holder.imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.arrow_downward)); } else { holder.imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.arrow_upward)); } }
static class ViewHolder { TextView textView; ImageView imageView; } }
В итоге получила именно то, что хотела:

3d анимация. При наведении на все, кроме основного блока, ломается эффект

Для примера поставил два блока, чтобы вы увидели, как анимация должна работать и как она работает.
Левый блок работает отлично: в зависимости от того, откуда наводят мышью, соответственно от этой стороны срабатывает эффект.
В правой стороне есть svg-иконка, которая при наведении выходит поверх синего окна.
Если навести, не задевая иконку или текст, можно и не заметить глюк. Но если навести сразу на svg-иконку, то глюк сразу можно увидеть. Немного "поигравшись" указателем внутри svg-иконки, не выходя из рамки svg, можно легко заметить проблему.
Ссылка: Codepen .
Я считаю, что тут проблема в css
Мои попытки:
1. Пытался дать position absolute этому блоку, но тогда все ломалось, и глюк также был
2. Пытался убрать display block из класса icon-close. Это не сработало тоже
И много других манипуляций с CSS, но ничего не помогло.
Очень прошу помогите.
var nodes = document.querySelectorAll('li'), _nodes = [].slice.call(nodes, 0); var getDirection = function (ev, obj) { var w = obj.offsetWidth, h = obj.offsetHeight, x = (ev.pageX - obj.offsetLeft - (w / 2) * (w > h ? (h / w) : 1)), y = (ev.pageY - obj.offsetTop - (h / 2) * (h > w ? (w / h) : 1)), d = Math.round( Math.atan2(y, x) / 1.57079633 + 5 ) % 4; return d; }; var addClass = function ( ev, obj, state ) { var direction = getDirection( ev, obj ), class_suffix = ""; obj.className = ""; switch ( direction ) { case 0 : class_suffix = '-top'; break; case 1 : class_suffix = '-right'; break; case 2 : class_suffix = '-bottom'; break; case 3 : class_suffix = '-left'; break; } obj.classList.add( state + class_suffix ); }; // bind events _nodes.forEach(function (el) { el.addEventListener('mouseover', function (ev) { addClass( ev, this, 'in' ); }, false); el.addEventListener('mouseout', function (ev) { addClass( ev, this, 'out' ); }, false); }); .icon-close { display: block; text-align: center; } .icon-close svg { margin-top: calc(70% / 2); margin-bottom: 20px; } .txt { text-decoration: none; text-align: center; display: block; color: blue; font-size: 22px; transition: 0.5s all ease; position: relative; z-index: 50; line-height: 1; } .container-inner { float: left; width: 100%; } .container-inner ul { margin: 0 auto; padding: 0; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap; flex-wrap: wrap; } .container-inner ul:after { content: ""; display: table; clear: both; } .container-inner ul li { background-color: rgba(255, 18, 156, 0.9); -webkit-perspective: 540px; perspective: 540px; position: relative; width: calc(25% - 10px); height: 290px; margin: 5px; padding: 0; list-style: none; } .container-inner ul li:hover svg { position: relative; z-index: 5; } .container-inner ul li:hover svg path { fill: white; } .container-inner ul li:hover .txt { color: white; } .container-inner ul li .info { -webkit-transform: rotate3d(1, 0, 0, 90deg); transform: rotate3d(1, 0, 0, 90deg); width: 100%; height: 100%; padding: 0px 10px; position: absolute; top: 0; left: 0; border-radius: 4px; pointer-events: none; background-color: rgba(26, 88, 156, 0.9); } .container-inner ul li .info p { color: #fff; } .in-top .info { -webkit-transform-origin: 50% 0%; -ms-transform-origin: 50% 0%; transform-origin: 50% 0%; -webkit-animation: in-top 300ms ease 0ms 1 forwards; animation: in-top 300ms ease 0ms 1 forwards; } .in-right .info { -webkit-transform-origin: 100% 0%; -ms-transform-origin: 100% 0%; transform-origin: 100% 0%; -webkit-animation: in-right 300ms ease 0ms 1 forwards; animation: in-right 300ms ease 0ms 1 forwards; } .in-bottom .info { -webkit-transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; transform-origin: 50% 100%; -webkit-animation: in-bottom 300ms ease 0ms 1 forwards; animation: in-bottom 300ms ease 0ms 1 forwards; } .in-left .info { -webkit-transform-origin: 0% 0%; -ms-transform-origin: 0% 0%; transform-origin: 0% 0%; -webkit-animation: in-left 300ms ease 0ms 1 forwards; animation: in-left 300ms ease 0ms 1 forwards; } .out-top .info { -webkit-transform-origin: 50% 0%; -ms-transform-origin: 50% 0%; transform-origin: 50% 0%; -webkit-animation: out-top 300ms ease 0ms 1 forwards; animation: out-top 300ms ease 0ms 1 forwards; } .out-right .info { -webkit-transform-origin: 100% 50%; -ms-transform-origin: 100% 50%; transform-origin: 100% 50%; -webkit-animation: out-right 300ms ease 0ms 1 forwards; animation: out-right 300ms ease 0ms 1 forwards; } .out-bottom .info { -webkit-transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; transform-origin: 50% 100%; -webkit-animation: out-bottom 300ms ease 0ms 1 forwards; animation: out-bottom 300ms ease 0ms 1 forwards; } .out-left .info { -webkit-transform-origin: 0% 0%; -ms-transform-origin: 0% 0%; transform-origin: 0% 0%; -webkit-animation: out-left 300ms ease 0ms 1 forwards; animation: out-left 300ms ease 0ms 1 forwards; } @-webkit-keyframes in-top { from { -webkit-transform: rotate3d(-1, 0, 0, 90deg); transform: rotate3d(-1, 0, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @keyframes in-top { from { -webkit-transform: rotate3d(-1, 0, 0, 90deg); transform: rotate3d(-1, 0, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @-webkit-keyframes in-right { from { -webkit-transform: rotate3d(0, -1, 0, 90deg); transform: rotate3d(0, -1, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @keyframes in-right { from { -webkit-transform: rotate3d(0, -1, 0, 90deg); transform: rotate3d(0, -1, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @-webkit-keyframes in-bottom { from { -webkit-transform: rotate3d(1, 0, 0, 90deg); transform: rotate3d(1, 0, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @keyframes in-bottom { from { -webkit-transform: rotate3d(1, 0, 0, 90deg); transform: rotate3d(1, 0, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @-webkit-keyframes in-left { from { -webkit-transform: rotate3d(0, 1, 0, 90deg); transform: rotate3d(0, 1, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @keyframes in-left { from { -webkit-transform: rotate3d(0, 1, 0, 90deg); transform: rotate3d(0, 1, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @-webkit-keyframes out-top { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(-1, 0, 0, 104deg); transform: rotate3d(-1, 0, 0, 104deg); } } @keyframes out-top { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(-1, 0, 0, 104deg); transform: rotate3d(-1, 0, 0, 104deg); } } @-webkit-keyframes out-right { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(0, -1, 0, 104deg); transform: rotate3d(0, -1, 0, 104deg); } } @keyframes out-right { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(0, -1, 0, 104deg); transform: rotate3d(0, -1, 0, 104deg); } } @-webkit-keyframes out-bottom { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(1, 0, 0, 104deg); transform: rotate3d(1, 0, 0, 104deg); } } @keyframes out-bottom { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(1, 0, 0, 104deg); transform: rotate3d(1, 0, 0, 104deg); } } @-webkit-keyframes out-left { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(0, 1, 0, 104deg); transform: rotate3d(0, 1, 0, 104deg); } } @keyframes out-left { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(0, 1, 0, 104deg); transform: rotate3d(0, 1, 0, 104deg); } }

  • Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper.

  • contact
    us •


Ответ

Я считаю, что тут проблема в css
тут проблема в том, что mouseover и mouseout срабатывает на дочернем элементе

mouseout
UPD: НЕ берём немного магии отсюда https://stackoverflow.com/a/4698240/4794368 т.к. при динамическом добавлении/удалении элементов могут возникнуть проблемы
лучше сделать так
el.addEventListener('mouseout', function (ev) { if (ev.currentTarget.contains(ev.relatedTarget))return; }, false);
https://developer.mozilla.org/en-US/docs/Web/Events/mouseout https://developer.mozilla.org/ru/docs/Web/API/Node/contains
ev.relatedTarget - куда ушла мышь ev.currentTarget - нода, которая подписана на событие (el) node.contains( otherNode ) - Возвращает true если otherNode является потомком node, или непосредственно самим node. В противном случае возвращает false
mouseover
чуть-чуть пишем сами
let qwa = false el.addEventListener('mouseover', function (ev) { if(qwa)return; qwa=!qwa }, false); el.addEventListener('mouseout', function (ev) { qwa=!qwa }, false);
результат
var nodes = document.querySelectorAll('li'), _nodes = [].slice.call(nodes, 0); var getDirection = function(ev, obj) { var w = obj.offsetWidth, h = obj.offsetHeight, x = (ev.pageX - obj.offsetLeft - (w / 2) * (w > h ? (h / w) : 1)), y = (ev.pageY - obj.offsetTop - (h / 2) * (h > w ? (w / h) : 1)), d = Math.round(Math.atan2(y, x) / 1.57079633 + 5) % 4; return d; }; var addClass = function(ev, obj, state) { var direction = getDirection(ev, obj), class_suffix = ""; obj.className = ""; switch (direction) { case 0: class_suffix = '-top'; break; case 1: class_suffix = '-right'; break; case 2: class_suffix = '-bottom'; break; case 3: class_suffix = '-left'; break; } obj.classList.add(state + class_suffix); }; // bind events _nodes.forEach(function(el) { let qwa = false el.addEventListener('mouseover', function(ev) { if (qwa) return; qwa = !qwa addClass(ev, this, 'in'); }, false); el.addEventListener('mouseout', function(ev) { if (ev.currentTarget.contains(ev.relatedTarget)) return; qwa = !qwa addClass(ev, this, 'out'); }, false); }); .icon-close { display: block; text-align: center; } .icon-close svg { margin-top: calc(70% / 2); margin-bottom: 20px; } .txt { text-decoration: none; text-align: center; display: block; color: blue; font-size: 22px; transition: 0.5s all ease; position: relative; z-index: 50; line-height: 1; } .container-inner { float: left; width: 100%; } .container-inner ul { margin: 0 auto; padding: 0; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap; flex-wrap: wrap; } .container-inner ul:after { content: ""; display: table; clear: both; } .container-inner ul li { background-color: rgba(255, 18, 156, 0.9); -webkit-perspective: 540px; perspective: 540px; position: relative; width: calc(25% - 10px); height: 290px; margin: 5px; padding: 0; list-style: none; } .container-inner ul li:hover svg { position: relative; z-index: 5; } .container-inner ul li:hover svg path { fill: white; } .container-inner ul li:hover .txt { color: white; } .container-inner ul li .info { -webkit-transform: rotate3d(1, 0, 0, 90deg); transform: rotate3d(1, 0, 0, 90deg); width: 100%; height: 100%; padding: 0px 10px; position: absolute; top: 0; left: 0; border-radius: 4px; pointer-events: none; background-color: rgba(26, 88, 156, 0.9); } .container-inner ul li .info p { color: #fff; } .in-top .info { -webkit-transform-origin: 50% 0%; -ms-transform-origin: 50% 0%; transform-origin: 50% 0%; -webkit-animation: in-top 300ms ease 0ms 1 forwards; animation: in-top 300ms ease 0ms 1 forwards; } .in-right .info { -webkit-transform-origin: 100% 0%; -ms-transform-origin: 100% 0%; transform-origin: 100% 0%; -webkit-animation: in-right 300ms ease 0ms 1 forwards; animation: in-right 300ms ease 0ms 1 forwards; } .in-bottom .info { -webkit-transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; transform-origin: 50% 100%; -webkit-animation: in-bottom 300ms ease 0ms 1 forwards; animation: in-bottom 300ms ease 0ms 1 forwards; } .in-left .info { -webkit-transform-origin: 0% 0%; -ms-transform-origin: 0% 0%; transform-origin: 0% 0%; -webkit-animation: in-left 300ms ease 0ms 1 forwards; animation: in-left 300ms ease 0ms 1 forwards; } .out-top .info { -webkit-transform-origin: 50% 0%; -ms-transform-origin: 50% 0%; transform-origin: 50% 0%; -webkit-animation: out-top 300ms ease 0ms 1 forwards; animation: out-top 300ms ease 0ms 1 forwards; } .out-right .info { -webkit-transform-origin: 100% 50%; -ms-transform-origin: 100% 50%; transform-origin: 100% 50%; -webkit-animation: out-right 300ms ease 0ms 1 forwards; animation: out-right 300ms ease 0ms 1 forwards; } .out-bottom .info { -webkit-transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; transform-origin: 50% 100%; -webkit-animation: out-bottom 300ms ease 0ms 1 forwards; animation: out-bottom 300ms ease 0ms 1 forwards; } .out-left .info { -webkit-transform-origin: 0% 0%; -ms-transform-origin: 0% 0%; transform-origin: 0% 0%; -webkit-animation: out-left 300ms ease 0ms 1 forwards; animation: out-left 300ms ease 0ms 1 forwards; } @-webkit-keyframes in-top { from { -webkit-transform: rotate3d(-1, 0, 0, 90deg); transform: rotate3d(-1, 0, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @keyframes in-top { from { -webkit-transform: rotate3d(-1, 0, 0, 90deg); transform: rotate3d(-1, 0, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @-webkit-keyframes in-right { from { -webkit-transform: rotate3d(0, -1, 0, 90deg); transform: rotate3d(0, -1, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @keyframes in-right { from { -webkit-transform: rotate3d(0, -1, 0, 90deg); transform: rotate3d(0, -1, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @-webkit-keyframes in-bottom { from { -webkit-transform: rotate3d(1, 0, 0, 90deg); transform: rotate3d(1, 0, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @keyframes in-bottom { from { -webkit-transform: rotate3d(1, 0, 0, 90deg); transform: rotate3d(1, 0, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @-webkit-keyframes in-left { from { -webkit-transform: rotate3d(0, 1, 0, 90deg); transform: rotate3d(0, 1, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @keyframes in-left { from { -webkit-transform: rotate3d(0, 1, 0, 90deg); transform: rotate3d(0, 1, 0, 90deg); } to { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } } @-webkit-keyframes out-top { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(-1, 0, 0, 104deg); transform: rotate3d(-1, 0, 0, 104deg); } } @keyframes out-top { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(-1, 0, 0, 104deg); transform: rotate3d(-1, 0, 0, 104deg); } } @-webkit-keyframes out-right { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(0, -1, 0, 104deg); transform: rotate3d(0, -1, 0, 104deg); } } @keyframes out-right { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(0, -1, 0, 104deg); transform: rotate3d(0, -1, 0, 104deg); } } @-webkit-keyframes out-bottom { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(1, 0, 0, 104deg); transform: rotate3d(1, 0, 0, 104deg); } } @keyframes out-bottom { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(1, 0, 0, 104deg); transform: rotate3d(1, 0, 0, 104deg); } } @-webkit-keyframes out-left { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(0, 1, 0, 104deg); transform: rotate3d(0, 1, 0, 104deg); } } @keyframes out-left { from { -webkit-transform: rotate3d(0, 0, 0, 0deg); transform: rotate3d(0, 0, 0, 0deg); } to { -webkit-transform: rotate3d(0, 1, 0, 104deg); transform: rotate3d(0, 1, 0, 104deg); } }

  • Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper.

  • contact
    us •