Страницы

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

понедельник, 30 марта 2020 г.

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

#sql #json #postgresql




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


Ответы

Ответ 1



в 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

Ответ 2



create table "test" ( "id" int, "before" jsonb, "after" jsonb ); insert into "test" ("id","before","after") values (1,'{"custom_targeting":{"include":{"zone_limitation":["1","2"]}}}','{"custom_targeting":{"include":{"zone_limitation":["2","1"]}}}'), (2,'{"custom_targeting":{"include":{"zone_limitation":["1","3"]}}}','{"custom_targeting":{"include":{"zone_limitation":["1","5"]}}}'); with t0 as ( select "id", json_array_elements(("before"#>'{"custom_targeting","include","zone_limitation"}')::json)::text "lz" from "test" ), t1 as ( select "id", json_array_elements(("after"#>'{"custom_targeting","include","zone_limitation"}')::json)::text "lz" from "test" ) select case when t0."id" is null then t1."id" else t0."id" end "id", (min(case when t0."id" is null or t1."id" is null then 0 else 1 end))::boolean "checher" from t0 full join t1 on t0."id" = t1."id" and t0."lz" = t1."lz" group by 1 order by 1 id | checher -: | :------ 1 | t 2 | f db<>fiddle here

Ответ 3



Не совсем понял, при чём тут сортировка. Вы пишете, что надо сравнить поля в пределах одной записи. Вообще говоря, такая таблица нарушает, насколько помню, даже первую нормальную форму — элементарность столбцов. Разумеется, никакой SQL-сервер с такими столбцами внятно работать не умеет. Можно, например, вынести из строк информацию, с которой вы намерены работать, в дополнительные столбцы. Например, коли уж вам нужен zone_limitation, сдублировать (либо вынести) в отдельные столбцы. Можно написать свой тип, написать к нему функций и операций.

Поиск папки на определенном уровне ssh

#ssh


Как сделать поиск папок на определенном уровне.
Конкретный пример:
Есть папка /www/
Нужно по такой схеме поискать папку core

/www/*/data/www/*/core


И вывести пути к ним.
    


Ответы

Ответ 1



не совсем ясно, к чему упомянут термин ssh, потому как к сути вопроса он явно не имеет никакого отношения. при использовании программы find: с помощью опций -mindepth и -maxdepth можно указать минимальную и максимальную глубину поиска а с помощью теста -type можно ограничить тип искомого объекта. итого: $ find /www -mindepth 5 -maxdepth 5 -type d -name core доп. чтение: $ man find

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

#php #json


Ниже представлен 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() может не рабоать?
    


Ответы

Ответ 1



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

Ответ 2



Но ничего не выходит, так как данные считываются не верно. Ниже - считывание данных. $data = json_decode(file_get_contents('php://input')); При условии, что у вас есть файл problem2.php и сервер слушает на localhost:80, а не на 8080 или другом порте. json_decode возвращает объект типа stdClass, обращатся к нему надо print_r($data->cells); Выхлоп: Array ( [0] => 4 [1] => 8 [2] => 11 [3] => 18 [4] => 19 )

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

#javascript


Вот у меня есть код:

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 этого объекта
    


Ответы

Ответ 1



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 при переходе между страницами сайта.

#php #javascript #css #html5


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


Ответы

Ответ 1



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

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

#linux #distribution


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

Как я понял, нужно оставить лишь папку bin, в которой сидит bash и его друзья. я прав?
    


Ответы

Ответ 1



Соберите свой, если есть часов 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 кастомных приложения, сами приложения больше, чем весь дистр.

Алгоритм не работает так как нужно

#c_sharp #оптимизация #генетический_алгоритм


Вот задача:


  Вы работаете с компанией по доставке товаров, которая ежедневно пользуется платной
  автомобильной дорогой. 
  
  Плата за путешествие взимается на 10-и пунктах оплаты
  расположенных вдоль дороги. Водителям компании необходимо преодолеть весь путь,
  оплатив комиссию за проезд на каждом из пунктов.
  
  Сложность состоит в том, что по правилам, комиссию можно оплачивать только одной
  единственной монетой. В случае, если ее номинал выше, чем стоимость проезда,
  водитель сдачу не получает и остаток сгорает. Если же монета, наоборот, не полностью
  покрывает стоимость проезда, то вашей компании насчитывается долг. 
  
  При этом
  стоимость проезда на каждом из пунктов абсолютно произвольно изменяется в конце дня,
  и может варьироваться в диапазоне от 1-ой до 10-и копеек включительно. Также
  известно, что несколько пунктов оплаты могут выставлять одну и ту же стоимость
  проезда, а общая сумма проезда через все пункты будет всегда больше 55-и копеек.
  
  Каждому водителю в начале пути выдается 10 монет, по одной монете каждого
  достоинства (т.е. одна монета достоинством в копейку, одна монета достоинством в две
  копейки, одна - три, и так далее, до десяти копеек включительно). 
  
  Используя генетический
  алгоритм, вам необходимо найти такую стратегию оплат путешествия, при которой долг
  водителя в конце пути будет минимальным. Алгоритм будет применяться компанией в
  начале каждого дня, и использовать данные по новым, только что установленным,
  размерам комиссий на пунктах оплат для получения новой стратегии для водителей.
  
  Входящие параметры:
  Массив из десяти произвольных чисел от 1 до 10, представляющих собой размеры
  комиссий на каждом из пунктов. Числа в массиве могут повторятся, и их сумма будет
  всегда больше чем 55.
  
  Выходные данные:
  Массив из десяти чисел, представляющих собой достоинства монет, расположенные в
  порядке, оптимальном для оплат на каждом из пунктов (так чтобы долг компании после
  всех оплат был минимальным).


Я скорее всего справился. В смысле алгоритма, но он не работает.

Вот код:

    class Program
{
    static void Main(string[] args)
    {
        Random rand = new Random();
        //bool weNeedContinue = true;          
        int[] propuski1 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] bestWay = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] propuski = PropuskiPrice(propuski1);
        int[] car0 = {0,0,0,0,0,0,0,0,0,0};
        int[] car1 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] car2 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] car3 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] car4 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] car5 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] car6 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] car7 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] car8 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] car9 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        GenerateCar(car0,bestWay);
        int[] moneyChange = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };                    
        for(int i = 0;i <10;i++)
        {
            GettingBest(moneyChange, car0, propuski, bestWay);
            GenerateCar(car0, bestWay);
            GenerateCar(car1, bestWay);

            GenerateCar(car2, bestWay);
            GenerateCar(car3, bestWay);
            GenerateCar(car4, bestWay);
            GenerateCar(car5, bestWay);
            GenerateCar(car6, bestWay);
            GenerateCar(car7, bestWay);
            GenerateCar(car8, bestWay);
            GenerateCar(car9, bestWay);

            //tournament begin
            int[] car23 = GenerateWinner(car2, car3, propuski);
            int[] car45 = GenerateWinner(car4, car5, propuski);
            int[] car67 = GenerateWinner(car6, car7, propuski);
            int[] car89 = GenerateWinner(car8, car9, propuski);

            int[] car2345 = GenerateWinner(car23, car45, propuski);
            int[] car6789 = GenerateWinner(car67, car89, propuski);

            int[] winner = GenerateWinner(car2345, car6789, propuski);
            int sumWinner = 0;
            for (int j = 0;j < 10; j++)
            {
                Console.WriteLine("stoimost proezda na punkte " + j + " " + propuski[j]);
                Console.WriteLine("deneg v karmane nomer " + j + " " + winner[j]);
                sumWinner = sumWinner + (winner[j] - propuski[j]);
            }
            Console.WriteLine("summa dolga= "+sumWinner);



            Console.ReadKey();
        }          

    }

    public static int[] PropuskiPrice(int[] a)
    {
        Random rand = new Random();
        int summa = 0;
        for (var i = 0; i < a.Length; i++)
        {
            a[i] = rand.Next(10) + 1;
            summa += a[i];
            if (i == 9 && summa <= 55)
            {
                PropuskiPrice(a);
            }
        }
        return a;
    }

    /////////////////////////////////////////////////////
    ////Создаем водителя/////////////////////////////////
    /////////////////////////////////////////////////////


    public static int[]  GenerateCar(int[] a,int[] c)
    {
        Random rand = new Random();

        for (int i = 0; i < a.Length; i++)
        {
            if(c[i] != 0)
            {
                a[i] = c[i];
                continue;
            }
            int b = rand.Next(1, 11);
            if (!a.Contains(b))
            {
                a[i] = b;
            }
            else
                i--;
            if(i == a.Length - 1 )
            {

            }
        }
        return a;
    }

    ////////////////////////////////////////////////////
    ////INIT////////////////////////////////////////////
    ////////////////////////////////////////////////////

    static void GettingBest(int[] change,int[] car,int[] propuski,int[] bestOne)
    {
        int changeSum = 0;
        for (int i = 0; i< 10; i++)
            {
                change[i] = car[i] - propuski[i];
                changeSum += change[i];
                if (change[i] == 0)
                {
                    bestOne[i] = car[i];
                Console.WriteLine("Карман" + car[i]);
                Console.WriteLine("Цена" + propuski[i]);
                Console.WriteLine("Лучший путь"+ bestOne[i]);
                }
            }




    }


    public static int[] GenerateWinner(int[] a, int[] b,int[] prises)
    {
        int[] changeA = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] changeB = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        int[] result = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        for (int i = 0;i < 10; i++)
        {
            changeA[i] = a[i] - prises[i];
            changeB[i] = b[i] - prises[i];
            if(Math.Abs(changeA[i]) > Math.Abs(changeB[i]))
            {
                result[i] = b[i];
            }
            else
            {
                result[i] = a[i];
            }
        }
        return result;
    }

}


В итоге, вот эту часть:

     for(int i = 0;i <10;i++)
        {
            GettingBest(moneyChange, car0, propuski, bestWay);
            GenerateCar(car0, bestWay);
            GenerateCar(car1, bestWay);

            GenerateCar(car2, bestWay);
            GenerateCar(car3, bestWay);
            GenerateCar(car4, bestWay);
            GenerateCar(car5, bestWay);
            GenerateCar(car6, bestWay);
            GenerateCar(car7, bestWay);
            GenerateCar(car8, bestWay);
            GenerateCar(car9, bestWay);

            //tournament begin
            int[] car23 = GenerateWinner(car2, car3, propuski);
            int[] car45 = GenerateWinner(car4, car5, propuski);
            int[] car67 = GenerateWinner(car6, car7, propuski);
            int[] car89 = GenerateWinner(car8, car9, propuski);

            int[] car2345 = GenerateWinner(car23, car45, propuski);
            int[] car6789 = GenerateWinner(car67, car89, propuski);

            int[] winner = GenerateWinner(car2345, car6789, propuski);
            int sumWinner = 0;


Начиная с 3-го, GenerateCar программа игнорирует. Посмотрите, в чем проблема?
    


Ответы

Ответ 1



Попробовал запустить код. У вас постоянно крутится один и тот же цикл внутри GenerateCar и из него не хочет выходить. Почему? Подумайте какое у вас условие выхода из цикла и почему оно не выполняется. Это первое замечание. Второе - вам нужно почитать очень популярный вопрос на сайте, с которым многие сталкиваются - о том, что Random всегда выдаёт одни и те же данные при одинаковом начальном значении. Подумайте: вы пытаетесь искать разные пути, но каждый раз перебираете одни и те же варианты. Третье. Почему вы генерируете 1..11 а не 0..11? Вы никогда не сгенерируете 0 - а потому вы не выйдете из цикла: int b = rand.Next(1, 11); // maybe should be int b = rand.Next(0, 10); Поправив я сразу выскочил из бесконечного цикла. PS У вас много копипасты. Программист не будет писать car0... car9 и копипастить подряд 10 раз GenerateCar. Нужно писать циклы, нужно использовать списки и массивы... а жать ctrl+c, ctrl+v -- это подход не программиста. В остальном -- нужно понимать, что за алгоритм вы реализуете или быть в теме "генетических алгоритмов". Я например имею только общие понятия о этой теме, поэтому вы в этом коде больше понимаете, чем я. Попробуйте словами описать, что тут к чему в коде.

Ответ 2



Чего-то такое получается Так как у нас по сути позиционная задача, будем использовать такой класс /// /// ДНК с фиксацией /// public class DNA { public bool Locked; public int Value; public override string ToString() { return $"{Value}->{Locked}"; } } т.е. если данный ДНК с нужным значением буден находится в нужной позиции, то для того, чтобы его в дальнейших мутациях не трогать мы полю Lock будем присваивать true. Следующий класс будет у нас геном или хромосомой :) я биологию совсем уже забыл... public class PaymentsState { public enum InitPayments { ForOffspring, ForHighway, ForDriver, } private readonly Random _random; public List Payments { get; private set; } public int Overpayment { get; private set; }//Fitness //ctor public PaymentsState(Random random, InitPayments init = InitPayments.ForOffspring) { _random = random ?? throw new ArgumentNullException(nameof(random)); Payments = new List(10); if (init == InitPayments.ForHighway) { GetPaymentsForHighway(); } else if (init == InitPayments.ForDriver) { GetPaymentsForDriver(); } else { } } /// /// Заполнение списка оплат для Водителя /// все типы монет 1..10 предствлены в отдном экземпляре /// в случайном порядке /// private void GetPaymentsForDriver() { var values = Enumerable.Range(1, 10).OrderBy(n => _random.Next(1, 10)) .ToList(); //заполняем список foreach (var val in values) Payments.Add(new DNA { Value = val, Locked = false }); } /// /// Создание списка оплат для Автострады /// /// private void GetPaymentsForHighway() { //сгенирируем массив из десяти чисел от 1 до 10 рассположенных в случ.порядке List values = Enumerable.Range(1, 10).OrderBy(n => _random.Next(1, 10)) .ToList(); //скорректируем под требование суммы int sum = 0; do { var index = _random.Next(0, 8); //просто копируем соседний элемент values[index] = values[index + 1]; sum = values.Sum(); } while (sum <= 55); //заполняем список foreach (var val in values) Payments.Add(new DNA { Value = val, Locked = false }); } /// /// Подсчет переплаты на основании переданного списка оплат /// /// список оплат у автотрассы /// значение переплаты public int CalcOverpayment(List highwayPayments) { if (highwayPayments.Count == 0) return 0; for (int i = 0; i < highwayPayments.Count; i++) { //если это ранее уже зафиксированный ген, //то пропускаем его if (Payments[i].Locked) continue; int val = highwayPayments[i].Value - Payments[i].Value; //в случае равенства (самая выгодная оплата) if (val == 0) { Payments[i].Locked = true; // фиксируем эту ДНК } else if (val < 0) { //В случае, если ее номинал выше, чем стоимость проезда, //водитель сдачу не получает и остаток сгорает. Overpayment += Math.Abs(val); } else // в случае полож.остатка он идет в долг, т.е. все равно в переплату { Overpayment += val; } } return Overpayment; } /// /// Скрещивание с другим геном и получение потомка /// /// другой PaymentState /// public PaymentsState Crossover(PaymentsState secondParent) { if (secondParent == null) throw new ArgumentNullException(nameof(secondParent)); //Здесь сложное наследование, т.к. каждая //монета должна быть представлена единожды и обязательно //т.е. если берем от мамы в позиции 1 монету 10, //то у папы мы уже не можем взять монету с этим же достоинством 10 //словарь для хранения использованных достоинств монет Dictionary usedCoins = Enumerable.Range(1, 10) .ToDictionary(n => n, n => false); //теперь у потомка должны быть гены от обоих родителей //зафиксированные гены должны занять те же самые позиции и значение //незафиксированные гены должны взять значение из словаря достоинств монет List offspringPayments = Enumerable.Range(1, 10).Select(n => new DNA { Value = 0 }) .ToList(); //определим у мамы(this) зафиксированные ДНК, //т.е. те, кот. не следует изменять var motherLockedDNAs = Payments.Where(p => p.Locked == true); //пробежимся по ним и включим их в словарь использованных монет //и добавим их в список для потомка foreach (DNA locked in motherLockedDNAs) { int index = Payments.IndexOf(locked); offspringPayments[index] = locked; //отмечаем использование монеты usedCoins[locked.Value] = true; } //определим у папы(secondParent) тоже var fatherLockedDNAs = secondParent.Payments.Where(p => p.Locked == true); foreach (DNA locked in fatherLockedDNAs) { //определим индекс который занимает int index = secondParent.Payments.IndexOf(locked); //если у матери такой монеты не было, //и этот индекс еще свободен if (!usedCoins[locked.Value] && offspringPayments[index].Value == 0) { offspringPayments[index] = locked; usedCoins[locked.Value] = true; } } //теперь нужно заполнить оставшиеся гены foreach (var payment in offspringPayments) { if (payment.Value == 0) { int val = usedCoins.First(kv => kv.Value == false).Key; payment.Value = val; usedCoins[val] = true; } } //готовим потомока var offspring = new PaymentsState(_random, InitPayments.ForOffspring); foreach (var payment in offspringPayments) offspring.Payments.Add(payment); return offspring; } /// /// Мутирование гена /// /// public void Mutate(double mutationRate) { //Сложное мутирование, т.к. каждое достоинстово монеты //должно быть обязательно и один раз for (int i = 0; i < Payments.Count; i++) { //если это ранее уже зафиксированный ген, //то пропускаем его if (Payments[i].Locked) continue; if (_random.NextDouble() < mutationRate) { //запоминаем монету int coinInner = Payments[i].Value; //новое случайное значение монеты int coinRandomValue = _random.Next(1, 10); //находим ген монеты с таким же значением DNA dna = Payments.First(p => p.Value == coinRandomValue); //если этот ген имеет статус зафиксированного //то ничего с ним делать не будем if (dna.Locked) continue; //находим индекс этого гена int index = Payments.IndexOf(dna); //запоминаем по этому индексу новый ген Payments[index] = new DNA { Value = coinInner }; //а по текущему индексу полученную из случайного знач. Payments[i] = dna; } } } } Класс автотрассы /// /// Автотрасса /// public class Highway { private readonly Random _random; private readonly PaymentsState _paymentsState; //ctor public Highway(Random random) { _random = random ?? throw new ArgumentNullException(nameof(random)); _paymentsState = new PaymentsState(_random, PaymentsState.InitPayments.ForHighway); } public List Payments => _paymentsState.Payments; public int PaymentSum => Payments.Select(p => p.Value).Sum(); public int MinOverpayment => PaymentSum - 55; } Ну и класс, который будет работать с популяцией и осуществлять для нас др.полезные вещи public class PaymentGeneticAlgorithm { private readonly Random _random; private List _tmpNewPopulation = new List(); private PaymentsState _bestPaymentsState; //лучшая позиция public List Population { get; set; } = new List(); public int Generation { get; private set; } //номер поколения public double MutationRate { get; private set; } //коэффициент мутации //ctor public PaymentGeneticAlgorithm(Random random, int populationSize, double mutationRate = 0.5) { _random = random ?? throw new ArgumentNullException(nameof(random)); MutationRate = mutationRate; for (int i = 0; i < populationSize; i++) { Population.Add(new PaymentsState(_random, PaymentsState.InitPayments.ForDriver)); } //в первый раз у нас лучшим будет просто первый _bestPaymentsState = Population[0]; } //-- public int BestOverpayment => _bestPaymentsState.Overpayment; //значение лучшей переплаты public List BestPayments => _bestPaymentsState.Payments.Select(p => p.Value).ToList(); //лучшие оплаты //-- /// /// Создание нового поколения популяции /// /// public void CreateNewGeneration(List highwayPayments) { //проверка входных данных if (highwayPayments == null) throw new ArgumentNullException(nameof(highwayPayments)); if (highwayPayments.Count <= 0) return; if (Population.Count <= 0) return; //выбор из популяции наиболее пригодного экземпляра _bestPaymentsState = CalculateFitness(highwayPayments); //готовим новую популяцию _tmpNewPopulation.Clear(); //будем скрещивать лучшего с оставшемися в популяции for (int i = 0; i < Population.Count; i++) { //выбор родителя var parent = Population[i]; //производим наследование или скрещивание var child = _bestPaymentsState.Crossover(parent); //подвергнем потомка мутации child.Mutate(MutationRate); //вносим потомка в новую коллекцию _tmpNewPopulation.Add(child); } //заменяем старую популяцию на новую var tmpList = Population; Population = _tmpNewPopulation; _tmpNewPopulation = tmpList; //увеличиваем счетчик поколений Generation++; } /// /// Проверка текущего поколения на пригодность /// Выявление лучшего гена наиболее подходящего под образец /// private PaymentsState CalculateFitness(List highwayPayments) { var best = _bestPaymentsState; for (int i = 0; i < highwayPayments.Count; i++) { var fitness = Population[i].CalcOverpayment(highwayPayments); //если переплата меньше, берем этот вариант if (fitness < best.Overpayment) best = Population[i]; } return best; } } Пользоваться всем этим счастьем можно так class Program { static void Main(string[] args) { Console.WriteLine("==Программа планирования платежей=="); Console.WriteLine(); var random = new Random(); var populationSize = 100; var mutationRate = 0.2; var highway = new Highway(random); var pga = new PaymentGeneticAlgorithm(random, populationSize, mutationRate); Console.WriteLine("Текущая ситуация на трассе"); PrintHighway(highway); Console.WriteLine(); Console.WriteLine("Для начала расчета нажмите любую клавишу"); Console.ReadKey(true); do { pga.CreateNewGeneration(highway.Payments.ToList()); Console.WriteLine("Трасса"); PrintHighway(highway); Console.WriteLine("Платежи"); PrintBestGenes(pga.BestPayments); Console.WriteLine($"Поколение: {pga.Generation}, Переплата: {pga.BestOverpayment}"); Console.WriteLine(new string('-', 80)); Console.WriteLine(); //Thread.Sleep(700); if (pga.Generation > 1000) break; } while (pga.BestOverpayment > highway.MinOverpayment); Console.ReadKey(); } private static void PrintBestGenes(IEnumerable bestGenes) { var payments = bestGenes.ToList(); var names = Enumerable.Range('A', payments.Count).ToList(); Console.Write("|"); Console.Write(new string('=', 5)); for (int i = 0; i < payments.Count; i++) { Console.Write($"[{(char)names[i]}:${payments[i]}]"); Console.Write(new string('=', 3)); } Console.Write(new string('=', 2)); Console.WriteLine("|"); } private static void PrintHighway(Highway highway) { var payments = highway.Payments.ToList(); var names = Enumerable.Range('A', payments.Count).ToList(); Console.WriteLine($"Общая сумма оплаты: {highway.PaymentSum}, минимально возможная переплата: {highway.MinOverpayment}"); Console.Write("|"); Console.Write(new string('=', 5)); for (int i = 0; i < payments.Count; i++) { Console.Write($"[{(char)names[i]}:${payments[i].Value}]"); Console.Write(new string('=', 3)); } Console.Write(new string('=', 2)); Console.WriteLine("|"); } }

TypeError: translate() takes exactly one argument (2 given)

#python


Есть папка с файлами, нужно удалить все цифры в названиях файлов. Из примера все
должно работать. Но у меня выкидывает ошибку. Если бы это можно было исправить- жизнь
стала бы прекрасна. Добавил 2 строчки, поправил,

    import os
def rename_files():
    #1
    file_list=os.listdir(r"C:\Users\Public\Documents\Python Scripts\prank\prank")
    #print(file_list)

    saved_path=os.getcwd()
    print("Current Workint Directory is"+ saved_path)
    os.chdir(r"C:\Users\Public\Documents\Python Scripts\prank\prank")

    #2
    for file_name in file_list:
        print("old name"+ file_name)
        print("New name"+ file_name.translate(None,"0123456789"))
        os.rename(file_name,file_name.translate(None,"0123456789"))
    os.chdir(saved_path)

rename_files()


TypeError: translate() takes exactly one argument (2 given)

    


Ответы

Ответ 1



bytes.translate и unicode.translate методы имеют разный интерфейс. В зависимости от версии Питона [тип str] и наличия from __future__ import unicode_literals обычные строковые константы типа 'abc' могут быть либо байтами либо Unicode. Код у вас написан, используя bytes.translate интерфейс, но 'abc' это Юникодная строка на Питоне 3 и поэтому несовместимая Юникодная версия translate метода вызывается — запуская Питон 2 код на Питон 3, вы получаете TypeError ошибку здесь. Используйте Unicode пути на Windows (объяснение почему см. в Как работать с путями c русскими символами?), тогда [в виде бонуса] код будет и на Питоне 2 так и 3 работать: remove_digits_table = dict.fromkeys(map(ord, u"0123456789")) no_digits = [name.translate(remove_digits_table) for name in os.listdir(u'C:\\Users\\name\\folder')] Если передать в os.listdir() Unicode, то и результат будет список Unicode имён, поэтому Юникодная версия translate() метода на обоих версиях вызывается, которая принимает словарь: номер символа -> строка на что заменить или None, чтобы удалить символ: >>> dict.fromkeys([1, 2, 3]) {1: None, 2: None, 3: None} Если не нужно Питон 2 поддерживать, то удобно pathlib модулем воспользоваться: #!/usr/bin/env python3 import string from pathlib import Path remove_digits_table = dict.fromkeys(map(ord, string.digits)) for path in Path(r'C:\Users\name\folder').iterdir(): path.replace(path.with_name(path.name.translate(remove_digits_table))) Здесь нет os.chdir() функции, которую стоит избегать, так как она затрудняет чтение кода и/или может препятствовать выполнению нескольких вещей одновременно в более крупных скриптах.

Ответ 2



Пример написан для Python2, а вы запускаете на Python3, поэтому и не работает. table = str.maketrans('', '', '0123456789') for file_name in file_list: ... print('New name' + file_name.translate(table)) ...

javascript создание модели данных

#javascript


Вопрос общий, о том как правильно делать.

В С# или Java  я создаю модели для манипулирования данных.
Например:

class Post
{
    public int id;
    public string title;
}


Тут же я могу задать дефолтные значения, и всегда знаю какие есть поля. 

В js тоже есть классы, но мне не понятно как организовывать их структуру в проекте,
 и правильный ли это подход?

Пример проблемы:  

Я получаю с сервера json такого вида

[
  {
    id:0,
    arr:['1','2']
  },
  {
    id:1,
  }
]


Теперь если я сделаю скажем так:

data[1].arr[0]//undefined 


то я получу ошибку. Ее не было бы если бы была модель которая описывать получаемые
данные с дефолтными значениями.

Вопрос: как правильно решать такую проблему в js? Если классами, то как организовать
проект(выносить каждый класс в отельный файл? А потом импортировать где нужно?). Может
как то помочь в этом вопросе typescript?
    


Ответы

Ответ 1



1. вашу проблему можно решить со стороны сервера Я получаю с сервера json такого вида 2. а можно со стороны клиента если не нужна проверка типов то проще сделать так: const user = { login: null, password: null, age: null, avatar: null, } let serverResponce = { user: { login: 'qwa', avatar: 'htttp://', } } let nUser = Object.assign({}, user, serverResponce.user) console.log(nUser) //{login: "qwa", password: null, age: null, avatar: "htttp://"} 3. TypeScript считается что TypeScript С#'ам ближе чем JS'ам и если не пугает: © Чего на самом деле не хватает? Нормального pattern matching-а, ну и иногда тоска накатывает из-за отсутствия typesafety. Но в такие моменты я обычно вспоминаю def myFunc[A, B >: C, E:A, D / E](a: A, b:B, c:C, d;D, e: E): [A / E] и как-то легче становится :) смотри https://www.typescriptlang.org/docs/handbook/decorators.html ключевые слова reflect-metadata @validate tsconfig.json { "compilerOptions": { "target": "ES5", "experimentalDecorators": true, "emitDecoratorMetadata": true } } ещё ссылок https://github.com/typeorm/typeorm https://github.com/typeorm/typescript-example https://github.com/typestack/routing-controllers и не забываем, что любая проверка типов это небольшая, но работа (не хочу писать замедление) UPD: ещё можно поискать что-либо на тему JSON валидации, но это выглядит более фантастично, чем проброс типов в JS из TS

Ответ 2



class Smth { constructor(info) { this.id = info.id; this.arr = info.arr || []; } } var data = [{ id:0, arr:['1','2'] },{ id:1, }]; data = data.map(x => new Smth(x)); console.log(data[1].arr.length);

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

#c_sharp #xml #binary


Создал 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();

    


Ответы

Ответ 1



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

Ответ 2



Как верно заметили в соседнем ответе, XDocument.ToString() не отображает декларацию документа, но ее можно вывести отдельно: Console.WriteLine(xdoc.Declaration); Console.WriteLine(xdoc);

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

#android




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

2) Внизу есть список из radioButton и поверх них зеленная линия вертикальная. Как
сделать эту линию в RecyclerView?
    


Ответы

Ответ 1



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

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

#python #нейронные_сети #машинное_обучение #keras


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

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


Ответы

Ответ 1



Вы можете воспользоваться 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)

Поиск и взятие по маске один и более раз

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


Требуется взять все то, что находится между (" "::" и между "::" ")

Пример:

текст текст (var1::var) текст текст (var2::var) текст текст


В этом случае var1 var и var2 var.

Так же, искомый текст может содержать любые символы
    


Ответы

Ответ 1



$text = 'Пример: текст текст (var1::var) текст текст (var2::var) текст текст'; preg_match_all("#\((.*)::(.*)\)#Uu", $text, $out, PREG_SET_ORDER); var_dump($out);

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

#php


Допустим есть функция, которая возвращает случайную цифру:

function getNumber()
{
    $Numbers = '1234567890';
    $NumbersSize = strlen($Numbers) - 1;
    $getNumber = $Numbers[rand(0, $NumbersSize)];
    return $getNumber;
}


Как заставить ее возвращать только нужную мне цифру, с помощью цикла?
    


Ответы

Ответ 1



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

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

#javascript #css #scrollbar


Вот столкнулся с такой проблемой что необходимо сделать скроллбар именно не активным
т.к. при скрытии скроллбара сайт разъезжается.
И в целом не вижу смысла делать всем элементам (боди и прочим стики элементам падинги).

Вот идеальный пример того что хочу это на сайте apple.com если кликнуть по поиску,
то скроллбар как бы остаётся и из него только пропадает сам бегунок и  получается аналогичный
эффект как при overflow:hidden, но при этом сайт не дергается на эти самые 10/13/16
пикселей.

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


Ответы

Ответ 1



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

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

#cpp #winapi #файловая_система


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?
    


Ответы

Ответ 1



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

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

#javascript #ооп


Куда сохраняются приватные свойства созданного объекта? Например у нас есть такой код:



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, но после создания нового объекта
через конструктор, этих свойств нет в этом объекте. И в глобальной области видимости
этих свойств тоже нет, куда они тогда сохраняются? 
    


Ответы

Ответ 1



Они хранятся в замыкании. Вот более просто пример этого механизма 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 #python #lxml


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


Ответы

Ответ 1



Встроенного метода вроде бы нет, но нетрудно написать свой. Проблема в том, что простой текст в 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'

Как работает lookbehind в js?

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


Ожидал, что выражение /(.)(?


Ответы

Ответ 1



Это происходит по той причине, что .* может найти пустую строку, а значит выражение (.)(?

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

#python #python_3x #pandas #dataframe


Есть датафрейм df. Есть фича feat имеющая три категории cat1, cat2, и немногочисленная
Unknown. 

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

В документации и блогах ничего подобного не нашел.  
    


Ответы

Ответ 1



Исходный 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

#python #excel


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


Ответы

Ответ 1



Можно написать функцию, возвращающую число результатов поиска. Пример: 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

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

#java #кодировка #поток_ввода #filewriter


Имеется утилита, которая запускает батники, которые в свою очередь собирают инфу
с помощью утилиты 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'е. Пошаманил с кодировками на открытии и получил фигу, упало как раз таки
из-за несовпадения кодировок, можно конечно перебрать вариантов там пара всего, но
хотелось бы узнать можно ли как-то это дело исправить. Это пока единственный мешающий/раздражающий
баг на данном этапе разработки утилитки.
    


Ответы

Ответ 1



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

Ответ 2



Очень помог ответ, Roman C. Получилась немного громоздкая конструкция со всеми этими обертками, но вроде бы работает осталось поправить другой метод, а именно networkAdapterProcessing(), чтобы корректно отображался результат, да и остальные методы можно оставить без изменений потому, что проблема только в сетевых устройствах, но вот решение самой проблемы с кодировками получилась весьма интересной хотя бы для меня, я еще пока только учусь. try(BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream(NETWORK_ADAPTER_INFO_PATH), "Unicode")); BufferedWriter writer = new BufferedWriter( new OutputStreamWriter( new FileOutputStream(TEMP_RESULT_FILE_PATH, true), "Unicode"))){ Так вот для того, чтобы определить кодировку достаточно было открыть файл клятым блокнотом и жамкнуть "Сохранить как", чтобы убедиться в том, что это Юникод. Причем пробовал вначале пересохранить в UTF-8, но там была полная борода. Сейчас конечно из-за того, что открывает с помощью другого инструмента сменилась и сама структура получаемой строки немного, но это уже мелочи по сравнению с раздражающей меня ошибкой с кодировкой. Как это у меня обычно и бывает проблема была в сути своей совсем не сложной, но мозги она заклинила неслабо. В будущем думаю исправлю, чтобы было все одинаково и не выделялось, но пока надо сделать хотя бы это. Спасибо вам за помощь.

из Mysql все данные приходят в string, как получить нужный тип?

#php #mysql


Сервер

Debian 4.9.65-3+deb9u1 (2017-12-23) x86_64
Mysql 5.7
PHP 7.2


Таблица в базе

CREATE TABLE `test` (
    `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
    `user` INT(11) NULL DEFAULT NULL,
    `project` INT(11) NULL DEFAULT NULL,
    `text` TEXT NULL COLLATE 'utf8_general_ci',
    PRIMARY KEY (`id`)
)
    COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=2;


Скрипт PHP

query("SELECT * FROM test WHERE id = 1")->fetch_object();
var_dump($product_name); 
$mysqli->close();


Ответ сервера

object(stdClass)#3 (4) { ["id"]=> string(1) "1" ["user"]=> string(1) "1" ["project"]=>
string(1) "2" ["text"]=> string(10) "Текст" }

через PDO пробывал, так же все в string

т.е всегда получаю string, может какой то модуль поставить надо ? Все ставил из стандартных
репозиториев и настройки по умолчанию
Хостинг Timeweb
    


Ответы

Ответ 1



Не всегда string приходит, обманываете! если будет NULL - то вернётся именно нормальный php-шный null. Остальное всё можно и ручками привести. Можно получать нужные типы. Легко (вру, тяжко и муторно): /** * Костыле-функция для получения PDO типа по native_type * @param string $native_type * @return int */ function getPDOType($native_type) { switch ($native_type) { case 'LONG': return PDO::PARAM_INT; // ... case 'VAR_STRING': default: return PDO::PARAM_STR; } } $pdo = db::connect(); $stmt = $pdo->prepare('SELECT `id`, `name` FROM `users` WHERE `id` = 600;'); $stmt->execute(); $col_cnt = $stmt->columnCount(); $row = []; for ($i = 0; $i < $col_cnt; $i++) { $meta = $stmt->getColumnMeta($i); $stmt->bindColumn( $i + 1, $row[$meta['name']], getPDOType($meta['native_type']) ); } $stmt->fetch(PDO::FETCH_BOUND); var_dump($row); //array(2) { // ["id"] => &int(600) // ["tema"] => &string(9) "Чебурашка" //} Посмотрите также пример в документации. Описание большей части параметров PDO::FETCH_* есть тут. Но я бы не стал использовать такой способ. С другой стороны, если написать ему какую-нибудь функцию-обёртку, которая будет "всё делать за меня" - возможно и пригодилось бы для чего-нибудь.

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

#bitbucket


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


Ответы

Ответ 1



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

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

#java #регулярные_выражения #строки


Есть входная строка:

String input = " 2777461-1

Стол: 1 < /td>"; Pattern pattern = Pattern.compile("\\+?(.*)"); Matcher matcher = pattern.matcher(input); while (matcher.find()) { System.out.println(matcher.group()); } необходимо создать из этой строки 3 переменные code = 2777461-1 furniture = Стол count = 1 ошибок нет, но и даже code не удалось получить результат: 2777461-1 Может я ошибаюсь и регулярными выражениями такое не решается?


Ответы

Ответ 1



Самый обычный вариант - использовать парсер, к примеру, jsoup. В вашем случае способ получить данные из документа будет выглядеть так: String input = " " + "2777461-1" + "

" + "" + "Стол: " + "

1

" + "
" + ""; Document html = Jsoup.parse(input); String strong = html.body().getElementById("strong").text(); String furniture = html.body().getElementById("furniture").text(); String count = html.body().getElementById("count").text(); Изучайте библиотеку, у нее есть масса способов парсинга html-документов. Ремарка: для доступа к данным проще использовать id, который вы назначаете на нужный тэг. К примеру, если в документе будет 2 тэга , то по id вытащить строку будет оптимальнее (я подправил ваш исходный html, обратите на это внимание).

Что значит аннотация @HotSpotIntrinsicCandidate?

#java #jvm #аннотации


Смотрел JVM, наткнулся на аннотацию @HotSpotIntrinsicCandidate, довольно часто ее
стал встречать. Что она значит? Раньше ее не было.
    


Ответы

Ответ 1



Начал искать дальше, вот что нашел в комментариях к аннотации(оказывается, и такие есть). The {@code @HotSpotIntrinsicCandidate} annotation is specific to the HotSpot Virtual Machine. It indicates that an annotated method may be (but is not guaranteed to be) intrinsified by the HotSpot VM. A method is intrinsified if the HotSpot VM replaces the annotated method with hand-written assembly and/or hand-written compiler IR -- a compiler intrinsic -- to improve performance. The {@code @HotSpotIntrinsicCandidate} annotation is internal to the Java libraries and is therefore not supposed to have any relevance for application code. Persons not directly involved with maintaining the Java libraries or the HotSpot VM can safely ignore the fact that a method is annotated with {@code @HotSpotIntrinsicCandidate}. Примерный перевод: Аннотация {@code @HotSpotIntrinsicCandidate} предназначена для HotSpot Virtual Machine. Это означает, что аннотированный метод может быть (но не гарантированно), встроен в HotSpot VM. Метод встроен, если HotSpot VM заменяет аннотированный рукописной сборкой и/или рукописным компилятором IR - встроенным компилятором - для повышения производительности. {@Code @HotSpotIntrinsicCandidate}аннотация является внутренней для Java библиотеки и поэтому не должна иметь никакого отношения к коду приложения. Лица, не имеющие непосредственного отношения к поддержке библиотек Java или HotSpot VM могут смело игнорировать тот факт, что метод аннотирован {@code @HotSpotIntrinsicCandidate}.

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

#php #интерфейс #рефлексия #php5


Можете, пожалуйста, подсказать почему в 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 лишён этого недостатка


Ответы

Ответ 1



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

Создать обрамляющую обводку для полигона в яндекс картах

#javascript #yandex_maps_api #gis


В конструкторе карт Яндекса при наведении мыши на полигон появляется обрамляющий
квадрат - https://yandex.ru/map-constructor/:

Подскажите как можно реализовать такой эффект?


    


Ответы

Ответ 1



Задача полностью решается средствами API: Вам нужно слушать на многоугольниках событие наведения мыши mouseenter По наведению мыши определять прямоугольную область, в которую вписан полигон. Для этого есть метод геометрии geometry.getBounds() - он возвращает координаты прямоугольника, который можно добавить на карту. В ответ на событие mouseleave полигона нужно скрывать прямоугольник-рамку, например, методом карты myMap.geoObjects.remove(). Ниже пример для одного полигона (для "универсальности" его понадобится доработать): ymaps.ready(init); function init() { var myMap = new ymaps.Map("map", { center: [55.73, 37.75], zoom: 10 }, { searchControlProvider: 'yandex#search' }); // Создаем многоугольник, используя вспомогательный класс Polygon. var myPolygon = new ymaps.Polygon([ // Указываем координаты вершин многоугольника. // Координаты вершин внешнего контура. [ [55.75, 37.50], [55.80, 37.60], [55.75, 37.70], [55.70, 37.70], [55.70, 37.50] ], // Координаты вершин внутреннего контура. [ [55.75, 37.52], [55.75, 37.68], [55.65, 37.60] ] ], { // Описываем свойства геообъекта. // Содержимое балуна. hintContent: "Многоугольник" }, { // Задаем опции геообъекта. // Цвет заливки. fillColor: '#00FF0088', // Ширина обводки. strokeWidth: 5 }); // Добавляем многоугольник на карту. myMap.geoObjects.add(myPolygon); var boundsRectangle; myPolygon.events.add("mouseenter", function(e) { bounds = myPolygon.geometry.getBounds(); boundsRectangle = new ymaps.Rectangle(bounds, { hintContent: 'Рамка многоугольника' }, { // Опции. // Цвет и прозрачность заливки. fillColor: '#777', fillOpacity: 0, // Цвет обводки. strokeColor: '#777', strokeOpacity: 0.7, // Ширина линии. strokeWidth: 5, zIndex: 0 }); myMap.geoObjects.add(boundsRectangle); }); myPolygon.events.add("mouseleave", function() { myMap.geoObjects.remove(boundsRectangle); }); } html, body, #map { width: 100%; height: 100%; padding: 0; margin: 0; }


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

#linux #tar


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

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


Ответы

Ответ 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

Ответ 2



Зависит от скорости диска и процессора. При медленном диске (c которого производится чтение) и быстром процессоре может оказаться быстрее разжать из архива, чем скопировать нежатое.

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

#cpp #c #препроцессор


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


Ответы

Ответ 1



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

Ответ 2



До кучи :) - в Visual C++ ключ /P создаст файл с тем же именем и расширением .i (можно изменить с помощью ключа /Fi), в который будут включены имена включаемых файлов и номера строк. В OpenWatcom -pl выведет информацию в stdout, для вывода в файл надо либо перенаправить вывод, либо указать имя с помощью ключа -fo.

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

#android #android_layout


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


    


Ответы

Ответ 1



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

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

#android #ui #android_spinner


Можно ли как-нибудь изменить кастомный макет для 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. Как это можно
сделать?
    


Ответы

Ответ 1



Создала кастомный адаптер для 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; } } В итоге получила именно то, что хотела:

Пользовательские MarkupExtension в качестве ключа словаря

#c_sharp #wpf #net #xaml


К примеру, имеем такое расширение разметки:

using System;
using System.Windows.Markup;
namespace CustomMarkupExtensions
{
    public class HelloExtension : MarkupExtension
    {
        public HelloExtension() { }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return "Hello";
        }
    }
}


Код XAML. Пытаюсь использовать расширение в качестве ключа в ResourceDictionary:



    Пример




При компиляции возникает ошибка:

(6,20): error MC3012: 
ключ словаря не может иметь тип "CustomMarkupExtensions.HelloExtension". 
Поддерживаются только типы String, TypeExtension и StaticExtension. Строка 6 позиция 20.


Хотя в описании директивы x:Key указано, что расширения разметки использоваться могут.
В чем дело?
    


Ответы

Ответ 1



В справке всё указано верно: в x:Key можно использовать расширения разметки, но только два: TypeExtension и StaticExtension. Пользовательские расширения разметки не поддерживаются, кроме наследников ResourceKey. (Также x:Key может содержать произвольное значение, но указать его можно только с помощью одного из перечисленных выше расширений разметки.) Это ограничение было снято в XAML 2009, вот только этот "стандарт" по сути не поддерживается. В XAML 2006, который, похоже, с нами навсегда, можно пойти обходным путём: положить значение в статическое свойство, затем указать его через x:Static.

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

#javascript #css


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

Левый блок работает отлично: в зависимости от того, откуда наводят мышью, соответственно
от этой стороны срабатывает эффект.  

В правой стороне есть 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 •


Ответы

Ответ 1



Я считаю, что тут проблема в 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 •