• Задача заполнения поля пазлами. Какие варианты решения?

    longclaps
    @longclaps
    sample = (("11", "1 1 2"),
              ("1111\n1111\n1111\n0100", "2 1 3\n3 1 1\n3 2 1"),
              ("000101\n001101\n110000\n111111\n001110\n111110",
               "1 1 2\n2 1 3\n3 1 1\n2 2 1\n6 1 2"),
              ("111\n101\n111", "2 1 4"))
    
    
    class Field:
        def flip(self):
            self.cells[:] = sorted((x, y) for y, x in self.cells)
            self.flipped ^= True
    
        def dismantle(self, cells, flipped):
            self.cells, self.flipped = cells, flipped
            left, right = cells[0][0], cells[-1][0]
            tmp = sorted(y for _, y in cells)
            top, bottom = tmp[0], tmp[-1]
            h, w = bottom - top + 1, right - left + 1
            if w * h == len(cells):
                wh = (w, h) if h < w else (h, w)
                c = tails.get(wh, 0)
                if c:
                    tails[wh] = c - 1
                    yield (self,)
                    tails[wh] = c
            for lo, hi in (left, right), (top, bottom):
                for i, (x, _) in enumerate(cells):
                    if lo < x <= hi:
                        for one in Field().dismantle(cells[:i], self.flipped):
                            for two in Field().dismantle(cells[i:], self.flipped):
                                yield [*one, *two]
                        lo = x
                self.flip()
    
    
    _field, _tails = sample[0]
    tails = {}
    for s in _tails.splitlines():
        w, h, c = map(int, s.split())
        if w < h:
            w, h = h, w
        tails[w, h] = c
    for partition in Field().dismantle(
            sorted((x, y) for y, s in enumerate(_field.splitlines())
                   for x, c in enumerate(s) if c == '1'), False):
        for f in partition:
            if f.flipped:
                f.flip()
            print(*f.cells)
        break
    else:
        print('не смогла')

    Ломается на 3м примере, "бублике". Это чинится, но лень возиться. Односвязные области должна решать всегда (if possible).
    Ответ написан
    Комментировать
  • Сравнить данные?

    @green_goo
    abs($number1 - $number2) < 0.02 * $number1
    Ответ написан
    1 комментарий
  • Как создать сервис для класса и передать туда аргументы Symfony 4?

    BoShurik
    @BoShurik Куратор тега Symfony
    Symfony developer
    https://symfony.com/doc/current/service_container/...

    services:
        _defaults:
            autowire: true
            autoconfigure: true
            bind:
                App\Repository\Repository $cachedRepository: '@App\Repository\User\CachedUserRepository'
    
        App\Repository\Repository: '@App\Repository\User\DoctrineUserRepository'
        App\Entity\UniqueEntityInterface: '@App\Entity\User'
    
        user_exists_checker:
            class: App\ExistsChecker
            bind:
                App\Repository\Repository: '@App\Repository\User\ApiUserRepository'


    Может пригодится, если несколько реализаций интерфейсов: https://symfony.com/blog/new-in-symfony-3-4-local-...

    Чтобы переопределить реализацию интерфейса для конкретного сервиса
    user_exists_checker:
        class: App\ExistsChecker
        bind:
            App\Repository\Repository: '@App\Repository\User\ApiUserRepository'


    Можно переопределить интерфейс для определенного названия переменной https://symfony.com/blog/new-in-symfony-4-2-autowi...
    _defaults:
            autowire: true
            autoconfigure: true
            bind:
                App\Repository\Repository $cachedRepository: '@App\Repository\User\CachedUserRepository'

    В примере выше, если в конструкторе вместо App\Repository\Repository $repository будете использовать App\Repository\Repository $cachedRepository, то вам придет App\Repository\User\CachedUserRepository
    Ответ написан
    2 комментария
  • Как протестировать метод, который вызывает методы другого класса?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега PHP
    class MyTest extends \PHPUnit\Framework\TestCase
    {
        public function testDoSomethingOne(): void
        {
            /** @var \PHPUnit\Framework\MockObject\MockObject $mockOfA */
            $mockOfA = $this->getMockBuilder(A::class)->getMock();
    
            $mockOfA->expects($this->once())
                ->method('setData')
                ->with(20);
    
            (new B)->doSomething($mockOfA, 1);
        }
    
        public function testDoSomethingTwo(): void
        {
            /** @var \PHPUnit\Framework\MockObject\MockObject $mockOfA */
            $mockOfA = $this->getMockBuilder(A::class)->getMock();
    
            $mockOfA->expects($this->once())
                ->method('setData')
                ->with(10000);
    
            (new B)->doSomething($mockOfA, 100);
        }
    }


    The practice of replacing an object with a test double that verifies expectations, for instance asserting that a method has been called, is referred to as mocking.

    https://phpunit.de/manual/6.5/en/test-doubles.html
    Ответ написан
    2 комментария
  • Можно ли вычислить страну по айпи адресу без обращений к сторонним сервисам?

    Ninazu
    @Ninazu
    Cкачать базу, и использовать ее локально
    https://dev.maxmind.com/geoip/geoip2/geolite2/
    Ответ написан
    Комментировать
  • Как валидировать внутренний массив в Symfony 4, который содержит объекты?

    BoShurik
    @BoShurik Куратор тега Symfony
    Symfony developer
    Если я правильно вас понял:
    $constraint = new Assert\Collection(
        [
            'fields' => [
                'cf_sub_products' => [
                    new Assert\NotBlank(),
                    new Assert\Type('array'),
                    new Assert\All([
                        new Assert\Collection([
                            'fields' => [
                                "size" => [
                                    new Assert\NotBlank(),
                                ],
                                "cf_product_id" => [
                                    new Assert\NotBlank(),
                                ],
                                "enabled" => [
                                    new Assert\NotBlank(),
                                ],
                                "price" => [
                                    new Assert\NotBlank(),
                                ],
                                "sku" => [
                                    new Assert\NotBlank(),
                                ],
                            ],
                        ])
                    ])
                ]
            ]
        ]
    );
    $violations = $validator->validate($body, $constraint);
    Ответ написан
    2 комментария
  • Как валидировать внутренний массив в Symfony 4?

    BoShurik
    @BoShurik Куратор тега Symfony
    Symfony developer
    https://symfony.com/doc/current/reference/constrai...
    'toEmail' => [
        new Assert\NotBlank(),
        new Assert\Type('array'),
        new Assert\All([
            'constraints' => [
                new Assert\NotBlank(),
                new Assert\Email(),
            ],
        ])
    ]
    Ответ написан
    Комментировать
  • Попросили проверить код, на что смотреть нужно?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Смотря зачем)). Я когда делаю Code Review критерии следующие:

    * Безопасность:
    - Каждый аргумент метода простого типа должен проверяться на тип в случае его проксирования и на граничные значения в случае обработки. Чуть что не так - бросается исключение. Если метод с кучкой аргументов на 80% состоит из поверки из аргументов - это вполне норм))
    - Никаких trigger_error, только исключения.
    - Исключения ДОЛЖНЫ быть человеко-понятны, всякие "Something went wrong" можно отдавать пользователю, но в лог должно попасть исключение со стектрейсом и человеко-понятным описанием, что же там пошло не так.
    - Каждый аргумент (объект) метода должен быть с тайпхинтингом на этот его класс, или интерфейс.
    - За eval как правило шлю на **й.
    - @ допускается только в безвыходных ситуациях, например проверка json_last_error.
    - Перед работой с БД - обязательная проверка данных.
    - Никаких == и !=. Со swtich - единственное исключение, по ситуации.
    - Если метод возвращает не только bool, а еще что-то - жесткая проверка с ===, или !== обязательна.
    - Никаких условий с присваиваниями внутри. while($row = ...) - тоже идет лесом.
    - Магические геттеры/сеттеры разрешаются только в безвыходных ситуациях, в остальном - запрещены.
    - Конкатенации в sql - только в безвыходных ситуациях.
    - Параметры в sql - ТОЛЬКО через плейсхолдеры.
    - Никаких глобальных переменных.
    - Даты в виде строки разрешаются только в шаблонах и в БД, в пхп коде сразу преобразуется в \DateTimeImmutable (в безвыходных ситуациях разрешено \DateTime)
    - Конечно зависит от проекта, но как приавло должно быть всего две точки входа: index.php для web и console(или как-то по другому назваться) - для консоли.

    * Кодстайл PSR-2 + PSR-5 как минимум, + еще куча более жестких требований (для начала все то что в PSR помечено как SHOULD - становится MUST)
    - В PhpStorm ни одна строчка не должна подсвечиваться (исключением является typo ошибки, например словарик не знает какой-то из аббревиатур, принятых в вашем проекте). При этом разрешается использовать /** @noinspection *** */ для безвыходных ситуаций.
    - Если кто-то говорит, что пишет в другом редакторе и у него не подсвечивается, на эти отговорки кладется ВОТ ТАКЕЕЕНЫЙ мужской половой **й и отправляется на доработку)).

    * Организация кода:
    - Никаких глобальных функций.
    - Классы без неймспейса разрешаются только в исключительно безвыходных ситуациях.

    * Тестируемость (в смысле простота тестирования) кода должна быть высокая.
    - Покрытие кода обязательно для всех возможных кейсов использования каждого публичного метода с моками зависимостей.

    * Принципы MVC:
    - Никаких обработок пользовательского ввода в моделях, от слова совсем.
    - Никаких ***ть запросов в БД из шаблонов.
    - Никаких верстки/js/css/sql-ин в контроллерах.
    - В моделях НИКАКОЙ МАГИИ, только приватные свойства + геттеры с сеттерами.
    - В моделях разрешено использовать метод save(при наличии такого разумеется) только в исключительных ситуациях. Во всех остальных - либо insert, либо update.

    * Принципы SOLD:
    - Никаких божественных объектов умеющих во все.
    - Если метод для внутреннего пользования - private, никаких public.
    - Статические методы разрешаются только в случае безвыходности.

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

    * Работа с БД:
    - Запрос в цикле должен быть РЕАЛЬНО обоснован.
    - За ORDER BY RAND() - шлю на***й.
    - Поиск не по ключам (конечно если таблица НЕ на 5 строк) запрещен.
    - Поиск без LIMIT (опять же если таблица НЕ на 5 строк) запрещен.
    - SELECT * - запрещен.
    - Денормализация БД должна быть обоснована.
    - MyISAM не используется (так уж)) )
    - Множественные операции обязательно в транзакции, с откатом если чо пошло не так.
    - БД не должна содержать бизнес логики, только данные в целостном виде.
    - Не должно быть нецелесообразного дерганья БД там, где без этого можно обойтись.

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

    * О людях:
    - "Я привык писать так и буду дальше" - не вопрос, ревью пройдешь только когда поменяешь свое мнение.
    - "Я пишу в vim-е и мне так удобно" - здорово, код консолью я тоже в нем пишу)) но есть требования к коду, если в них не сможешь - не пройдешь ревью.
    - "Я скопировал этот страшный метод и поменял 2 строчки" - это конечно замечательно, но по блейму автор всего этого метода ты, так что давай без говняшек, хорошо?
    - "Оно же работает!" - вот эта фраза переводится примерно так: "да, я понимаю, что пишу полную хрень, но не могу писать нормально потому, что руки из жо", я правильно тебя понял?))
    - "У меня все работает!" - рад за тебя, а как на счет продакшна?
    - "Там все просто" - не используй слово "просто", от слова "совсем". Вот тебе кусок кода (первого попавшегося с сложной бизнес логикой), где там ошибка (не важно есть она, или нет)? Ты смотришь его уже 2 минуты, в чем проблема, там же все "просто"))

    * Всякое:
    ActiveRecord (это я вам как в прошлом фанат Yii говорю) - полное говно, примите за исходную. По факту у вас бесконтрольно по проекту гуляют модельки с подключением к БД. Не раз натыкался на то, что в тех же шаблонах вызывают save, или update (за такое надо сжигать).
    То, что используется Laravel - это печально((. Что бы выполнить требования приведенные выше, приходится "воевать" с фреймворком.

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

    UPD

    Формализировал данные критерии по ссылочке: https://github.com/index0h/php-conventions
    Ответ написан
    55 комментариев
  • Как искать в aggregate Mongo?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Не следует использовать стадию $match внутри оператора $sum на стадии группировки.

    db.operations.aggregate([
    	{
    		$match: {"address" : "Office 1"}
    	},
    	{
    		$project: {
    			address: "$address",
    			received: {
    				$cond: [ {$eq: ["$operation_type", "receive"]}, "$amount", 0 ]
    			},
    			sent: {
    				$cond: [ {$eq: ["$operation_type", "send"]}, "$amount", 0 ]
    			},
    			dateTime: "$dateTime"
    		} 
    	}, 
    	{
    		$group: {
    			_id: {
    				address: "$address",
    				day: { $dayOfYear: "$dateTime" },
    				year: { $year: "$dateTime" }
    			},
    			received: {
    				$sum: "$received"
    			},
    			sent: {
    				$sum: "$sent"
    			}
    		}
    	}
    ])
    Ответ написан
    Комментировать
  • Генерация аватаров как на Гитхабе?

    profesor08
    @profesor08 Куратор тега JavaScript
    Сама по себе генерация таких аватаров не составляет особого труда. Любым способом получаем мешанину из однотипных символов на основе введенных данных, window.crypto с этим справляется, остается их интерпретация - codepen.io
    Ответ написан
    Комментировать
  • Объясните, почему не срабатывает await?

    rockon404
    @rockon404
    Frontend Developer
    О причине вам уже написали. Поделюсь примером как заставить ваш код работать:
    async function my_function() {
      console.log('1');
      await new Promise(resolve => {
        setTimeout(() => {
          console.log('2');
          resolve();
        }, 1000);
      });
      console.log('3');
    }


    Или можно вынести функцию setAsyncTimeout:
    function setAsyncTimeout(cb, timeout) {
      return new Promise(resolve => {
        setTimeout(() => {
          cb();
          resolve();
        }, timeout);
      });
    }
    
    async function my_function() {
      console.log('1');
      await setAsyncTimeout(() => { console.log('2'); }, 1000);
      console.log('3');
    }
    Ответ написан
    Комментировать
  • Как организовать роутинг из базы данных в Symfony 4?

    Stalker_RED
    @Stalker_RED
    проблема заключается что в каждой таблице категории или продукта есть соответствующее поле slug
    Можно сделать представление, где будут slug'и со всех таблиц.

    Но и идея собрать все их в одну таблицу тоже неплоха - позволит контролировать их уникальность средствами БД.

    и через сервис вытащить нужную логику
    Есть же forwarding
    Ответ написан
    4 комментария
  • Как запустить AJAX в цикле?

    Negezor
    @Negezor
    Senior Shaurma Developer
    function fetchData() {
      $.ajax({
        // ...
        success: function(data) {
          if (data === 'someData') {
             return window.location.reload();
           }
    
            setTimeout(fetchData, 8e3);
        }
      });
    }
    
    fetchData();
    Ответ написан
    3 комментария
  • Это вообще люди делают?

    dimovich85
    @dimovich85 Куратор тега CSS
    https://u-academy.net/
    Поделюсь с вами вот такой ссылкой:
    https://www.youtube.com/playlist?list=PLswdBLT9llb...
    Ответ написан
    1 комментарий
  • Вывод данных из MySql?

    kimono
    @kimono
    Web developer
    Запрос должен быть примерно таким:
    SELECT LEFT(`name`, 1) `abc`, `id`, `name` FROM `persons` ORDER BY `name` ASC;

    На выходе вы получите такой массив:
    $data = [
      ['abc' => 'а', 'id' => 1, 'name' => 'Абрамов Михаил Фёдорович'],
      ['abc' => 'а', 'id' => 2, 'name' => 'Агутин Юрий Николаевич'],
      ['abc' => 'б', 'id' => 4, 'name' => 'Баринов Олег Юрьевич'],
    ];

    Далее проходим по всему массиву и складываем по начальным буквам:
    $alphabet = [];
    foreach ($data as $row){
      $alphabet[$row['abc']][$row['id']] = $row['name'];
    }

    Получается что-то подобное:
    $alphabet = [
      'а' => [
        1 => 'Абрамов Михаил Фёдорович',
        2 => 'Агутин Юрий Николаевич',
      ],
      'б' => [
        4 => 'Баринов Олег Юрьевич',
      ],
    ];

    Дальше, я думаю, вы уже сами догадались:
    foreach($alphabet as $alpha => $rows){
      echo '<h2>'.$alpha.'</h2>';
      echo '<ul>';
      foreach ($rows as $id => $name){
        echo '<li><a href="/person?id='.$id.'">'.$name.'</a></li>';
      }
      echo '</ul>';
    }
    Ответ написан
    Комментировать
  • Yii Как избежать дублирование методов в классах?

    kimono
    @kimono
    Web developer
    Можно ещё через interface + trait:
    interface StatusListable
    {
        public function getStatusName(): string;
    }
    
    trait StatusReturner
    {
        public static function getStatusDescriptions()
        {
            return [
                self::STATUS_NOT_PAID => 'Не оплачено',
                self::STATUS_PAID => 'Оплачено',
                self::STATUS_CANCEL => 'Отменена',
            ];
        }
    
        public function getStatusName($status): string
        {
            return ArrayHelper::getValue(self::getStatusDescriptions(), $status);
        }
    }
    Ответ написан
    1 комментарий
  • Aлгоритм подбора 5 ближайщих сумм при покупке товара?

    longclaps
    @longclaps
    На питоне так:
    coins = [1, 2, 5, 10, 20, 50, 100]
    
    def roundup(cost):
        return sorted(set((cost + c - 1) // c * c for c in coins))
    
    print(roundup(30))   # [30, 40, 50, 100]
    print(roundup(312))  # [312, 315, 320, 350, 400]

    а специфика арифметики и структур данных php - это уж сам )
    зы и еще, откуда там 325?
    Ответ написан
    1 комментарий
  • Возможно ли сделать нагрузочное тестирование локально?

    sim3x
    @sim3x
    Да
    Ставите виртуалку
    Деплоите проект, так как он будет на продакшене
    Долбите его снаружи с хоста запросами

    Долбать можно
    ab (Apache HTTP server benchmarking tool)
    yandex tank
    jmeter
    Ответ написан
    Комментировать