• Как изменить поля в модели через n-времени в Yii2?

    @Holyboom Автор вопроса
    junior fullstack
    короч как сделал .
    поставил плагин для yii "composer require --prefer-dist yiisoft/yii2-queue"
    в common/config/main добавил
    'components' => [
            'queue' => [
                'class' => \yii\queue\file\Queue::class,
                'path' => '@console/runtime/queue',
                'as log' => \yii\queue\LogBehavior::class,
            ],
    'bootstrap' => [
            'queue',
        ],


    создал класс отвечающий за таски
    <?php
    class QueueHelper
    {
        public static function setTask ($task) {
            Yii::$app->queue->push($task);
        }
        public static function setDelayTask ($task , $delay = 5) {  // delay  - задержка выполнения в сек
            Yii::$app->queue->delay($delay)->push($task);
        }
    }


    и класс с самой таской
    class TaskEndEvent extends BaseObject implements \yii\queue\JobInterface
    {
        public $idTask;
        public function execute($queue)
        {
            $e = Events::findOne($this->idTask);
            if ($e->status != 1 ){
                $e->ended_at = $e->creation_at + 7200 ;
                $e->status = 1 ;
                $e->save(false);
            }
        }
    }


    и сделал вызов при сохранении
    public function afterSave($insert, $changedAttributes)
        {
            parent::afterSave($insert, $changedAttributes);
            if ($this->status != 1){
                QueueHelper::setDelayTask(new TaskEndEvent(['idTask'=>$this->id]), 7200);
            }
        }


    и кроном запустил проверку на наличие актуальных таск
    cron run * * * * * /usr/bin/php /var/www/my_project/yii queue/run


    можно повесить слушатель таск в консоли
    yii queue/listen
    Ответ написан
    Комментировать
  • Как получить гео-точки из видимой области на карте при изменении угла карты?

    @Holyboom Автор вопроса
    junior fullstack
    короче как я решил этот вопрос.
    тк мне не нужна супер точность я использовал такую формулу :
    //dist расстояние , в моем случает от центра карты до лев верх угла карты в метрах.
    // те это то расстояние от центра на котором мы поставим наши точки 
    // a  = угол на который наклонить точки относительно нулевого азимута.
    // lat и  long координаты точки в центре экрана 
    var p180= 180/pi;
          var dx =  p180 * ((cos(a / 180 * pi) * dist) / 6378137) ;
          var dy =  p180 * ((sin(a / 180 * pi) * dist) / 6378137) ;
          var toplat = latitude + dy;
          var toplng = longitude + dx / cos(latitude);
          var bottomlat = latitude - dy;
          var bottomlng = longitude - dx / cos(latitude);
    Ответ написан
    Комментировать
  • Как сделать двойную группировку в запросе SQL в ElasticSearch?

    @Holyboom Автор вопроса
    junior fullstack
    Короче решил вопрос так

    $topLeftLat = $_POST['topLeftLat'];
            $topLefiLng = $_POST['topLeftLng'];
            $bottomRightLat = $_POST['bottomRightLat'];
            $bottomRightLng = $_POST['bottomRightLng'];
            $zoom = $_POST['zoom'];
    
            $params['bool']['filter'][]['bool']['must']=
                [
                    [
                        "exists" => [
                            "field" => "location"
                        ]
                    ],
                    [
                        "geo_bounding_box" => [
                            "location" => [
                                "top_left" => $topLeftLat.','.$topLefiLng,
                                "bottom_right" => $bottomRightLat.','.$bottomRightLng
                            ]
                        ]
                    ]
                ];
            $query = ElasticObj::find();
            $p = ($zoom > 10 )? 10 : 8-(6-$zoom);
                $query->addAggregate('gridSplit', [
                    'geotile_grid' => [
                        'bounds' => [
                            "top_left" => $topLeftLat.','.$topLefiLng,
                            "bottom_right" => $bottomRightLat.','.$bottomRightLng
                        ],
                        "field" => "location",
                        "precision" => $p,
                        "size" => 65535,
                        "shard_size" => 65535
                    ],
                    'aggs' => [
                        'gridCentroid' => [
                            'geo_centroid' => [
                                'field' => 'location'
                            ]
                        ]
                    ]
                ]);
                $query->query($params);
                $dataProvider = new ActiveDataProvider([
                    'query' => $query,
                ]);
                $aggregations = $dataProvider->getAggregations();
    Ответ написан
    Комментировать
  • Как сделать множественный поиск по БД?

    @Holyboom Автор вопроса
    junior fullstack
    Короче вариант с поисковым движком типа сфинкс или подобного не подходит , тк мой проект сейчас находится не на выделенном серваке и у меня нет прав запуска различных служб.
    покачто вышел из ситуации как

    SELECT s.* ,st.`name` AS type_name ,  group_concat(DISTINCT benefits.name SEPARATOR ' ') as concat_bn, st.alias as spot_type_alias, benefits.alias as benefit_alias, CONCAT(" ", group_concat(DISTINCT benefits.id SEPARATOR ' ')  ," ")  as concat_bn_id,
      // для полей s.name , s.track, st.name , st.alias ,benefits.name , benefits.alias в каждой таблице создаем полнотекстовый индекс. 
      // 
      // тут считаем релевантность запроса
      MATCH(s.name , s.track) AGAINST('+$query') as score,
      MATCH(st.name , st.alias) AGAINST('+$query') as stcore,
      MATCH(benefits.name , benefits.alias) AGAINST('+$query') as bncore,
       (                // тут считаем расстояние до точки (тк я ищу точки ) (опционально)
                        6371 *
                        acos(cos(radians($lat)) *
                        cos(radians(s.lat)) *
                        cos(radians(s.lng) -
                        radians($lng)) +
                        sin(radians($lat)) *
                        sin(radians(s.lat)))
                        ) AS distance 
    FROM `spots` s
    // прикручиваем связь один к одному для поиска по типу из другой таблицы
    JOIN `spot_type` st ON s.id_spot_type = st.id
    // прикручиваем сводную таблицу для связи многие ко многим для поиска по типам плюшек на точке 
    join spots_benefits
     on spots_benefits.spot = s.id
    join benefits 
     on benefits.id = spots_benefits.benefit
    
    where 
    //собственно сам поиск
      MATCH(s.name, s.track) AGAINST('+$query')
      OR MATCH(st.name, st.alias) AGAINST('+$query')
      OR MATCH(benefits.name, benefits.alias) AGAINST('+$query')
      // групируем элементы из сводных таблиц в одно поле груп_конкат
    group by s.id 
    // ищем по только те что были добавлены в фильтр (опционально) типов 
    HAVING  concat_bn_id like "% 1 %" AND concat_bn_id like '% 2 %' AND  s.id_spot_type = 2
    // сортируем сначала по релевантности, а потом уже по расстоянию
    ORDER BY (score + stcore + bncore) DESC, distance ASC


    как-то так... запрос в принципе быстро обрабатывает (примерно 0,005 - 0,01 ) относительно конечно , но для бд с 20к записей норм
    если у кого есть идеи по оптимизации буду рад вашему мнению ! )
    всем спасибо
    Ответ написан
    Комментировать
  • Как кастомизировать gridview flutter?

    @Holyboom
    junior fullstack
    я юзаю этот пакет flutter_staggered_grid_view.
    глянь там , там реализовать такое просто.
    Ответ написан
    Комментировать
  • Алгоритм получения квадрата по координатам?

    @Holyboom Автор вопроса
    junior fullstack
    Сергей Соколов, короче , вроде сделал))
    SET @home = ST_GeomFromText('LINESTRING(
    //Список наших точек через которые идет маршрут 
    53.862263 27.483486,
    53.871521 27.493636,
    53.875594 27.496447,
    53.880938 27.500744,
    53.882699 27.505121,
    53.884246 27.504435,
    53.891446 27.500293,
    53.896630 27.497375,
    53.905348 27.496302,
    53.912531 27.495487,
    53.918726 27.496882)');
    SELECT *, ST_AsText(geo) as Coord,
        // Дистанция считается странно получается вроде правильно , но не уверен насчет точности . 
       // В оригинале в доках написано умножать ее на .001 для км и .00067... для миль
       // но у меня так не работало и показывало до объекта 0,003км хотя по факту до него 300м вот я решил 
             умножать ее на 100 (хотя хз может оно там сантиметрах считает) 
        ST_DISTANCE(@home, geo) * 100 AS dist
        FROM dots
       // дистанция от маршрута в радиусе которой нам нужны точки (в км ) 
        HAVING dist < 1
        ORDER BY dist
        LIMIT 30


    и в итоге будет примерно так
    613cb908956cd964506159.png

    вернет зеленые точки , а красные нет .

    вроде так )
    Ответ написан
  • Flutter как сделать секундомер так чтобы он работал в фоне, когда приложение переключилось на другой экран?

    @Holyboom Автор вопроса
    junior fullstack
    Короче запилил глобальный сервис с таймером и отдельно просто прикрутил AndroidAlarmManager чтобы он следил за открытием закрытием приложения .

    Пока что выглядит так
    Сам сервис

    class TimerService extends ChangeNotifier {
          Stopwatch _watch = Stopwatch();
          var _timer;
     
          Duration get currentDuration => _currentDuration;
          Duration _currentDuration = Duration.zero;
         bool get isRunning => _timer != null;
    
         TimerService() {
            _watch = Stopwatch();
         }
    
        String get getTime => getDisplayTime(_currentDuration.inMilliseconds);
    
         static String getDisplayTime(){
         //перевод человеко читаемый вид(если кому надо пишите скину код) 
         }
    
        void _onTick(Timer timer) {
          _currentDuration = _watch.elapsed;
          print(_currentDuration);
          // notify all listening widgets
          notifyListeners();
        }
    
        void start() {
           if (_timer != null) return;
           _timer = null;
           _timer = Timer.periodic(Duration(seconds: 1), _onTick);
           _watch.start();
           notifyListeners();
        }
    
        void stop() {
          _timer?.cancel();
          _watch.stop();
          _currentDuration = _watch.elapsed;
          notifyListeners();
        }
    
        void reset() {
          stop();
          _watch.reset();
          _currentDuration = Duration.zero;
          notifyListeners();
        }
        }
    
         class TimerServiceProvider extends InheritedWidget {
           const TimerServiceProvider({Key? key, required this.service, required Widget 
           child})
            : super(key: key, child: child);
     
          final TimerService service;
    
          @override
          bool updateShouldNotify(TimerServiceProvider old) => service != old.service;
        }


    и слушатель

    AnimatedBuilder(
                                    animation: globalsVars.timerServ,
                                    builder: (context, child) {
                                      return Column(
                                        mainAxisAlignment: MainAxisAlignment.center,
                                        children: <Widget>[
                                      Container(
                                          padding: EdgeInsets.only(top: 5 , left: 12),
                                          decoration: (selectedButton == key)
                                              ? BoxDecoration(
                                            border: Border.all(
                                              color: Colors.white10,
                                              width: 2,
                                            ),
                                            borderRadius: BorderRadius.circular(5),
                                          )
                                              : null,
                                          child:  Text(
                                            '${globalsVars.timerServ.getTime}',
                                            style: GoogleFonts.roboto(
                                                textStyle: TextStyle(
                                                  color: Colors.red,
                                                  fontWeight: FontWeight.w700,
                                                  fontSize: 16.sp,
                                                )),
                                          ))
                                        ],
                                      );
                                    },
                                  ),


    Пока что более элегантного решения не придумал ... так что если у кого есть мысли буду рад вашему мнению
    Ответ написан
    Комментировать
  • Как передать данные в переменную?

    @Holyboom
    junior fullstack
    $newVar = $resultDeal->time['date_start']
    Если $resultDeal это тоже ассоциативный массив то
    $newVar = $resultDeal['time']['date_start']
    Ответ написан
    Комментировать
  • Возможно ли изменить свойство родителя при наведении на дочерний элемент средствами css?

    @Holyboom
    junior fullstack
    насколько мне изветно нельзя . тк в css нисходящее дерево зависимостей .
    если конечно вы имеете ввиду что надо сделать чтото типо ul>li>a и обратится от а к li нельзя . в какомто из препроцессорах scss less можно было так делать .
    Ответ написан
    3 комментария