Страницы

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

воскресенье, 15 декабря 2019 г.

Как получить лучшего лайкера? VK API, PHP

#php #vkontakte_api


Есть задача - нужно получить лучшего лайкера постов за неделю. При помощи каких методов
лучше всего это реализовать? (Пытался собирать все посты в массив и после прогонять
каждый отдельный пост через likes.get, но по коду получилось очень объемно и есть проблемы
с ограничениями на количество запросов в секунду к VK api)
    


Ответы

Ответ 1



На самом деле тут нужно подумать, не все так просто, хотя недавно передо мной стояла задача сделать аналогичную функцию для вывода самого активного пользователя недели на обложку группы. И вот я делюсь с вами парочкой вариантов как это можно сделать: Итак, первый вариант: Он очень схож с описанием вашего варианта реализации, то есть, получаем записи с определенной группы с помощью метода wall.get (с учетом специального фильтра1), далее используем метод likes.get и проходим по отфильтрованным постам, получаем списки пользователей, остается только подсчитать и выбрать самого активного. Плюсы: Получение точных данных на текущий момент, то бишь на момент запроса. Минусы: Большой объем данных и длительное время их получения. Второй вариант идентичен первому, но суть в том, что он является не полным: Он строится таким образом, что скрипт получает данные самого активного юзера не за неделю, а за сутки. Таким образом имеем данные всех пользователей поставивших лайк за сутки (при желании выделяем самого активного за 1 день). Итак, спустя 7 дней на основе полученных данных строится статистика и подсчет самого активного. Неактуальные данные, которым больше недели, удаляются, и загружаются новые. Плюсы: Тут можно сказать, что это палка о двух концах, как бы много времени не теряем (если получаем данные за сутки), все происходит быстро, но если смотреть с другой стороны, нужно ждать неделю, чтобы сказать наверняка. Минусы: Манипуляции пользователей, то есть, в течении недели, пользователь может убрать лайк на определенной записи, или же новый пользователь может добавить. Итак, можно сделать вывод, что если мы заранее получили данные (а после чего на загруженных нами постами случались манипуляции в виде убранного/добавленного лайка), то можем считать, что у нас данные являются устаревшими. Специальный фильтр1 — это логика, с помощью которой скрипт подгружает исключительно посты те, где дата с момента публикации не превышает больше одной недели. Касаемо ограничения токена на 3 запроса в секунду, могу посоветовать использовать массив токенов (скажем около 10), и совсем недавно открыл для себя то, что можно использовать генераторы (подр. см. здесь), или функцию со статический переменной (подр. см. здесь). Простой пример реализации, имеем массив токенов: $data = ['token', 'token2', 'token3', 'token4']; И у нас, допустим, имеется огромный цикл, около 1000 итераций, чтобы не использовать один токен на протяжении всех итераций, можно задействовать их по порядку из массива, с помощью функцией ниже (пример реализации функции со статической переменной): function demark($data) { static $i = 0; return $data[$i++ % count($data)]; } И, когда мы запустим цикл в котором итераций будет больше, чем токенов в массиве, тогда увидим, что как только токены в массиве заканчиваются, их отсчет начинается сначала: for ($i = 0; $i < 10; ++$i) echo $i.' => '.demark($data), PHP_EOL; В результате получаем следующий результат (демо см. здесь): 1 iteration => token 2 iteration => token2 3 iteration => token3 4 iteration => token4 5 iteration => token 6 iteration => token2 7 iteration => token3 8 iteration => token4 9 iteration => token 10 iteration => token2 Лично я использовал 2-ой вариант, но склонен к тому, что разумнее использовать первый, так как он является более точным и практичным по сравнению со вторым.

Ответ 2



Рекомендую использовать метод execute позволяющий объединить 25 запросов в одном. Первым запросом с помощью метода wall.get можно забирать 25*100=2500 постов, далее допустим 100*25 запросов likes.get. Даже если подстраховаться от лимитов VK поставив между запросами sleep(1) скрипт должен отработать за 2-3 минуты.

Преобразование случайной величины с равномерным распределением в величину с нормальным распределением

#cpp #математика #теория_вероятностей


У меня есть некое кол-во случайных величин float в диапазоне [0;1] и эти величины
имеют равномерное распределение.

Если такая величина X имеет нормальное распределение, то, величина
K = m + a * tan(PI*(X-0.5)) имеет распределение коши.

Возможно ли по аналогии преобразовать такую величину X, в величину имеющую нормальное
распределение?
    


Ответы

Ответ 1



Написал грубо и точно (2.5%) функцию InverseErf. Она очень сложна для вычислений. // g++ inverf.cpp -o inverf # include # include // -1 => -Inf ; 0 => 0 ; +1 => Inf // -0.82 .. +0.82 => третья степень // 0.82 .. 1.0 => сложно double InverseErf(double x){ bool flagneg = (x < 0.0); x=fabs(x); double result; if(x<0.82) result = (x*x*0.37+0.88)*x; else { x=log(1.0-x); double const HalfPi = 1.57 ; result = sqrt(-x-log(-HalfPi*(log(HalfPi)+2.0*x))/2.0);} return flagneg ? -result : result ; } double SimpleToNormal(double x , double med , double sigma){ return med + sqrt(2.0)*sigma*InverseErf(2.0*x-1.0);} int main() { std::cout<<"inverf(0.999)="<

Исправить прерывистое рисование на CANVAS

#canvas


Если вести мышь медленно, то промежутков нет, но стоит немного ускорить, появляются
очень большие пробелы. Как можно исправить? Или нужен вообще другой подход?



const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1024;
canvas.height = 678;


canvas.onmousedown = function() {
  let flag = true;
  draw();
  canvas.onmousemove = function() {
    if (flag == true) {
      draw();
    }
  }
  canvas.onmouseup = function() {
    flag = false;
  }
  canvas.onmouseout = function() {
    flag = false;
  }
};

function draw() {
  let x = event.offsetX;
  let y = event.offsetY;
  ctx.fillStyle = 'black';
  ctx.fillRect(x, y, 5, 5);

}






    


Ответы

Ответ 1



Естественно, будет просвет между Вашими квадратиками, если Вы двинули мышь больше, чем на пять пикселей. const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); canvas.width = 1024; canvas.height = 678; var oldPoint = null; let flag = false; canvas.onmousedown = function(e) { flag = true; draw(e); }; canvas.onmousemove = function(e) { if (flag == true) { draw(e); } }; canvas.onmouseup = function() { oldPoint = null; flag = false; }; canvas.onmouseout = function() { oldPoint = null; flag = false; }; function draw(event) { if (!oldPoint) { oldPoint = { x: event.offsetX, y: event.offsetY }; } ctx.moveTo(oldPoint.x, oldPoint.y); ctx.lineTo(event.offsetX, event.offsetY); ctx.strokeStyle = "#FF0000"; ctx.stroke(); oldPoint.x = event.offsetX; oldPoint.y = event.offsetY; } canvas { border: 1px solid; }

Jquery validator - проверка на email или телефона в одном поле input

#html #jquery #css #jquery_validation


Думаю использовать плагин JQuery validator чтобы не писать скрипт с нуля. По ТЗ задание
такое. 


  В поле можно будет ввести или номер телефона или mail. Соответственно
  нужна будет проверка: номер телефона должен состоять минимум из 10
  цифр (+ код страны). Если в значении будет присутствовать знак “@”, то
  мы будем идентифицировать его как эл.адрес. Перед знаком “@”  и после
  него должны быть расположены хотя бы по одному символу, а третий
  символ справа должен быть точкой. Если значение заполнено не будет,
  или будет заполнено не корректно, то будет выдаваться сообщение:
  “Заполните это поле” (для номера телефона) или “Укажите верный
  эл.адрес” (для эл.адреса).


Как сделать такую валидацию на JQuery Validator то есть на этом https://jqueryvalidation.org/
    


Ответы

Ответ 1



Да вам даже jquery и валидаторы не нужны. Если только вы не хотите писать какой-то волшебный текст. Можно сделать через html pattern
Something:


Ответ 2



Вам необходимо реализовать и добавить своё правило в котором Вы будете проверять значение элемента на соответствие или номеру телефона или eMail. Используйте для этого jQuery.validator.addMethod(). Примеров масса: раз, два, три...

Ответ 3



Можно попробовать так Сначала проверяем на пустоту поля, затем проверяем в поле одни цифры или есть буквы, если есть буквы, то проверяем на правильность ввода e-mail, если только цифры, то проверяем кол-во введенных цыфр $(document).ready(function() { $('#text').click(function() { var val = $('#input').val(); if(val != '') { if(/[^[0-9]/.test(val)){ var pattern = /^([a-z0-9_\.-])+@[a-z0-9-]+\.([a-z]{2,4}\.)?[a-z]{2,4}$/i; if(pattern.test(val)){ $('#valid').text('E-mail введен верно'); } else { $('#valid').text('Не верно введен e-mail'); } } else { if(val.length >= 10) { $('#valid').text('Телефон введен верно'); } else { $('#valid').text('Не верно введен номер телефона'); } } } else { $('#valid').text('Поле input не должно быть пустым'); } }); });


Как сделать окна в стиле Windows 7?

#c_sharp #windows #winforms #style


Подскажите как сделать окна, в точности повторяющие стиль Windows 7? 

Например, как эти



    


Ответы

Ответ 1



Операционная система Windows поддерживает только один "хром" окон и не включает поддержку стилей хрома предыдущих версий Windows, поэтому с помощью WinAPI вы не сможете добиться стиля Windows 7 на Windows 10. (Условно поддерживается "классическая" тема, вроде, но это вас явно не интересует.) Вы можете попытаться эмулировать стиль хрома предыдущей оси, но в случае эмуляции конкретно стиля Aero из Windows 7 это особенно трудно, потому что нужно воспроизвести не только все стили всех кнопок, но и прозрачность с замыливанием. Насколько мне известно, такой эффект может себе позволить ось, потому что она имеет эффективный доступ ко всем "слоям", а вот на уровне приложения его эмуляция будет затратна. Картинки кнопок можно вытянуть из ресурсов системных библиотек Windows 7, но лицензионно это, разумеется, запрещено. В целом я бы советовал вам не слишком увлекаться стилями хрома без веской на то причины. Пользователь ожидает, что хоть хром-то будет единообразен, по нему можно будет угадать, какое окно активно, например. В приложениях, которые активно используют хром, например, в современных браузерах, которые размещают в заголовке ушки вкладок, обычно наоборот стараются воспроизвести текущий стиль оси.

Как запросить , разрешена ли на устройстве “Установка из небезопасных источников”?

#java #android #android_studio


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


Ответы

Ответ 1



Вкратце, чтобы пользователи с Android API 25 и ниже могли устанавливать из небезопасных источников, они должны включить параметр "Неизвестные источники" в настройках. 1 Примечание: Когда пользователи пытаются установить неизвестное приложение на устройстве под управлением Android 7.1.1 (уровень 25 API) или ниже, система иногда показывает диалоговое окно которое спрашивает пользователя, независимо от того, хотят ли они позволить только одного конкретного неизвестного приложения для установки. Почти во всех случаях пользователи должны позволить только одно неизвестное приложение установки в то время, если параметр доступен для них. 1 boolean isNonPlayAppAllowed = Settings.Secure.getInt(getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS) == 1; if (!isNonPlayAppAllowed) { startActivity(new Intent(android.provider.Settings.ACTION_SECURITY_SETTINGS)); } 3 А для того, чтобы пользователи с Android API 26 и выше, могли устанавливать из небезопасных источников необходимо предоставить разрешение. 1 Добавить в manifest.xml 2 Затем самое основное: 2 private void checkIsAndroidO() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { boolean result = getPackageManager().canRequestPackageInstalls(); if (result) { installApk(); } else { ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.REQUEST_INSTALL_PACKAGES}, INSTALL_PACKAGES_REQUESTCODE); } } else { installApk(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case INSTALL_PACKAGES_REQUESTCODE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { installApk(); } else { Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES); startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES); } break; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case GET_UNKNOWN_APP_SOURCES: checkIsAndroidO(); break; default: break; } } Источники: 1, 2, 3

Изменить fragment 2 из fragment 1

#java #android #android_fragment #fragment_manager


Условия: Имеется приложение с Activity и тремя fragment'ами, которые можно листать
смахивая влево - вправо как страницы (Этот эффект осуществляется благодаря ViewPager).

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

То есть работает так:


Когда виден фрагмент 1: 1 (загружен/видно) - 2 (подгружен)       - 3 (выгружен)
Когда виден фрагмент 2: 1 (подгружен)       - 2 (загружен/видно) - 3 (подгружен)
Когда виден фрагмент 3: 1 (выгружен)       - 2 (подгружен)       - 3 (загружен/видно)




Код создания фрагментов (в Activity):

public class MainActivity extends FragmentActivity
{
    public final int FRAGMENT_ONE = 0; //идентификатор первого фрагмента
    public final int FRAGMENT_TWO = 1; //идентификатор второго фрагмента
    public final int FRAGMENT_THREE = 2; //идентификатор третьего фрагмента
    /** список фрагментов для отображения. */
    private final List _fragments = new ArrayList();


                               *** Остальной код ***


    @Override
    public void onResume()
    {
        super.onResume();

        //Создаем фрагменты.
        _fragments.add(FRAGMENT_ONE, new FirstFragment());
        _fragments.add(FRAGMENT_TWO, new SecondFragment());
        _fragments.add(FRAGMENT_THREE, new ThirdFragment());

        // Настройка фрагментов, определяющих количество фрагментов, экраны и название.
        FragmentPagerAdapter MainAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {

            @Override
            public int getCount() {return 3;} //Получаем количество фрагментов

            @Override
            public Fragment getItem(final int position) {return _fragments.get(position);}

            @Override
            public CharSequence getPageTitle(final int position) {

                switch (position) {
                    case FRAGMENT_ONE:
                        return "Title One";
                    case FRAGMENT_TWO:
                        return "Title Two";
                    case FRAGMENT_THREE:
                        return "Title three";
                    default:
                        return null;
                }
            }
        };

        ViewPager pager = (ViewPager) findViewById(R.id.pager); //Инициализируем
ViewPager
        pager.setAdapter(MainAdapter); //Устанавливаем Adapter для Viewpager


        int startPage = 1

        pager.setCurrentItem(startPage); //На каком фрагменте будет открываться 
    }

}




Задача: На каждом фрагменте есть картинка и кнопка. При нажатии на кнопку видимого
фрагмента, на остальных фрагментах должна поменяться картинка.


  С фрагментами которые выгружены - проблем нет. Перед тем как загрузится,
  они проверяют нужно ли менять картинку и, если нужно,
  подгружаются уже с изменённой картинкой:

         //Проверяем нужно ли менять картинку
        int ActivePage = strorageFileExemp.getInt(APP_STORAGE_LAST_PAGE, 8);
        if (ActivePage == 1 || ActivePage == 2)
        {
            ImageView MyImageView = view.findViewById(R.id.my_imageview_id);
            MyImageView.setImageResource(R.drawable.my_image);
        }



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


  Допустим, возьмём случай, когда виден фрагмент 1:
  
  1(загружен/видно) - 2(подгружен) - 3 (выгружен). 
  
  Я нажимаю кнопку на фрагменте 1. Фрагмент 3 изменит картинку, когда будет загружаться,
а вот в уже подгруженном, но ещё не видном фрагменте 2 не понимаю как поменять картинку.


Yellastro предложил рабочее, но не самое лучшее решение. Оно достаточно сложное и
создаёт свои неудобства. Поэтому вопрос всё ещё открыт и новые предложения активно
рассматриваются.
    


Ответы

Ответ 1



В вашем случае, когда три разных класса делают по сути одно и тоже (провоцируют смену картинок на остальных фрагментах и меняют свою картинку по какому то внешнем условию), лучше будет сделать просто для них суперкласс, примерно такой: public abstract class PictureChangingFragment extend Fragment { private MainActivity mActivity; //Надо запросить в конструкторе Активность, которая будет иметь ссылки на все фрагменты public PictureChangingFragment(MainActivity fActivity) { super(); mActivity = fActivity; } public void onChangePicture(ImageView fImageView) { //ваш код смены картинки у конкретного фрагмента } //Этот метод должен вызываться когда вы нажимаете на текущую картинку, или //когда еще вы захотите поменять картинки на соседних фрагментах public void changePictureOnOtherFragments() { //Теперь мы можем тупо через главную активность обратиться // ко всем остальным фрагментам и поменять на ни картинки for ( PictureChangingFragment qFragment :mActivity.mFragments) if(qFragment!=this) { ImageView fImageView = (ImageView) qFragment.FindviewById(R.id.*imageView*) Fragment.onChangePicture(fImageView); } } Затем нужно наследовать ваши классы фрагментов от этого абстрактного класса. И поменять формат вашего списка фрагментов в главной активности. Во первых он должен быть публичный, что бы сами фрагменты могли им пользоваться. А во вторых он будет типизированн соглассно нашему новому классу: class MainActivity... { ... Public List mFragments = new ArrayList<>(); ... И вот. Теперь нам не надо проверять при загрузке фрагментов ничего, смена картинок будет происходить в тот же момент, когда для этого было выполнено условие (нажатие картинки то есть. Если вы в функции нажатия конечно добавите соответствующую функцию) Upd. Прошу прощения за несколько мелких ошибок в моем коде, это они вызвали у вас часть вопросов. Сейчас все исправил. 1) В вашей активности место создания фрагментов теперь должно выглядеть так _fragments.add(FRAGMENT_ONE, new FirstFragment(this)); _fragments.add(FRAGMENT_TWO, new SecondFragment(this)); _fragments.add(FRAGMENT_THREE, new ThirdFragment(this)); Что бы ваши фрагменты могли принимать такой параметр, см. пункт 4 2) Вью в этом случае может быть фрагментом, как раз их мы и перебираем в цикле функции changePictureOnOtherFragment(). В коде выше я исправил все что бы работало. Вообще, когда вы переопределяете событие нажатия по вью, вы работаете с методом onClick(View view). И вот эта view, которую метод получает в параметрах, и есть ваша ImageView, если вы конечно назначили этот метод на прослушивание нажатий по картинке. То есть вам нужно сейчас в этом методе onClick(View view) дописать строчки ImageView imgView = (ImageView)view;//преобразование абстрактной вью к формату вью-картинки onChangePicture(imgView);//этот метод в моем классе я только переписал выше. 3) Это была моя ошибка, там просто буквы перепутались 4) Да, правильно. Обозначение классов ваших фрагментов теперь должно выглядеть так public class *FragmentName* extends PictureChangingFragment. И ещё им нужен новый формат конструктора: public *fragmentName*(MainActivity mActivity) { super(mActivity); ... }

Ответ 2



Просто перенеси ту конструкцию которая меняет картинки при загрузки из функции onCreate в onResume. Тогда каждый фрагмент будет менять картинку как раз перед своим отображением. Upd Раз не получается использовать по назначению onResome(), тогда делай все фрагменты экземплярами интерфейса PicturesChangeListener с одним методом onPictureChange(), и вызывай этот метод через for(PicturesChangeListener qFragment : твой список фрагментов) qFragment.onPictureChange();