Страницы

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

вторник, 17 декабря 2019 г.

Тестовый продукт для тестирование подписки на Android в Unity3D

#java #android #c_sharp #unity3d


Создаю подписку для Android в первый раз, на IOS есть возможность использовать тестовый
продукт даже для подписки, есть ли тестовый продукт для тестирования подписки на Android
платформе ?, и где его взять?.
    


Ответы

Ответ 1



Как таковых, специальных тестовых подписок не существует. Но можно тестировать на обычных Создаёте продукт-подписку Выкладываете приложение в альфа/бэта тест. Прописываете мыло юзера-тестировщика в консоли в 2 местах (бета тест и какие-то общие настройки аккаунта) Юзер идёт по ссылке на бета-тест приложения, соглашается и качает с маркета бета версию. В ней он может за 0р купить любую подписку в приложении. Она будет возобновляться каждый день. Вот ещё вопросы по теме: “Этот продукт не продается” Billing Тестирование In-app Billing в андроид

Демонстрация экрана средствами браузера

#php #javascript #html #css


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

На площадке есть такая возможность, ведущий вебинара по нажатию одной кнопки транслирует
свой экран только лишь средствами браузера. 

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

К примеру, на самом сайте просматривать демонстрацию. С серверной частью разберусь. 
    


Ответы

Ответ 1



JS: const videoElem = document.getElementById("video"); const startElem = document.getElementById("start"); const stopElem = document.getElementById("stop"); // Options for getDisplayMedia() var displayMediaOptions = { video: { cursor: "never" }, audio: false }; // Set event listeners for the start and stop buttons startElem.addEventListener("click", function(evt) { startCapture(); }, false); stopElem.addEventListener("click", function(evt) { stopCapture(); }, false); async function startCapture() { try { let screen = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions); videoElem.srcObject = screen sendInfo(screen); } catch(err) { console.error("Error: " + err); } } function stopCapture(evt) { let tracks = videoElem.srcObject.getTracks(); tracks.forEach(track => track.stop()); videoElem.srcObject = null; } function sendInfo(data) { // Тут отправляем 'data' на сервер /* Как отобразить данные из видео videoElem.srcObject = (здесь данные с сервера) */ } HTML:

 


CSS: #video { border: 1px solid #999; width: 98%; max-width: 860px; } Тут не обязателен HTTPS, не нужны внешние ресурсы.

Как уменьшить нагрузку на базу данных?

#mysql #оптимизация


Занимаюсь разработкой и поддержкой движка на Laravel для сервиса  партнерских программ.
Текущий трафик, который идёт на сервер порядка 30 миллионов посещений в сутки. К базе
постоянно идёт ~1500 запросов в секунду. Это нормально и сервер с этим справляется
отлично, но как только количество запросов возрастает до 6000 в секунду, сервер начинает
откровенно подвисать. 

В связи со сложившейся ситуацией возник вопрос, а как вообще можно разгрузить базу?
СУБД MySQL, таблицы на InnoDB. Движок написан на Laravel.

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

Таблицы проиндексированы. Также используется CloudFlare.
    


Ответы

Ответ 1



В плане железа использовать горизонтальное или вертикальное масштабирование. Но в вашем случае конечно лучше использовать горизонтальное, в реализации сложнее - но потом проще масштабировать. В плане кода: Если у вас много JOIN в запросах. Опишу на примере: Есть таблица leads, и вспомогательные leads_attrs, leads_params, leads_times и т.д. Многие создают метод получения лидов сразу со всеми параметрами и далее используют его по всему проекту. Но можно пересмотреть все места использования и проверить, везде ли требуется подключение всех вспомогательных таблиц leads_attrs, leads_params, leads_times? Количество выгружаемых данных по запросам. Если есть к примеру таблица users, в которой присутствует 25 таблиц. Обычным SELECT * FROM users WHERE 1 вы будете получать огромное количество данных. В таких местах требуется проверить, все ли данные требуются? Обычно требуется 3-5 параметров, остальные тянутся тяжелой ношей. И самое главное кеширование. В PHP фреймворках реализовано хорошее кеширование из коробки, его стоит использовать. Только в случае с кешированием главное не "переборщить". Требуется кешировать общие данные, которые чаще всего повторяются. Пример: на сайте есть таблица городов, которая каждый раз выгружается из базы, весь список городов лучше закешировать и каждый раз брать из кеша - нежели на каждой странице дёргать sql.

Как для теста отправить 1000 запросов с binary file через Postman?

#postman


Хочу сделать следующий тест для своей программы - отправить 1000 запросов с binary
file через postman.

Вопрос в том, как это сделать? Мне не удалось найти способ прикрепить binary file
в Postman runner. Возможно есть другие инструменты, которые можно посоветовать, но
интересует в первую очередь Postman.

ОС Windows

Можно было бы попробовать сделать это на Yandex tank, но мне не удалось найти способ
установить его на Windows. За подробный гайд (для человека не работающего с linux)
был бы благодарен
    


Ответы

Ответ 1



Возможно я не до конца понял проблему, но вообще это делается без хитростей. Создать в коллекции необходимый запрос с body payload который необходим (прикрепить файл) (см. скрин) Создать test run с необходимым количеством итераций этого запроса Run

Анимация появления фрагмента

#android #android_fragment #анимация #android_animation


Я хочу анимировать появление фрагмента. При чем чтобы он появлялся "сверху вниз".
 Мне частично удалось реализовать задумку, но проблема в том что сначала появляется
место на экране под фрагмент, а только потом появляется сам фрагмент с анимацией. Как
сделать одновременную анимацию появления места на экране и анимацию появления фрагмента? 

Вот что имею:





Экран разметки




    

    
    

    




Методы, запускающие анимацию

private void calendarShow() {
    FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    t.setCustomAnimations(R.animator.calendar_show, R.animator.calendar_hide);
    t.replace(R.id.calendarView, mCalendar, CALENDAR_TAG);
    t.show(mCalendar);
    t.commit();
    mCalendar.refreshView();
}

private void calendarHide() {
    android.support.v4.app.FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    t.setCustomAnimations(R.animator.calendar_show, R.animator.calendar_hide);
    t.hide(getSupportFragmentManager().findFragmentByTag(CALENDAR_TAG));
    t.commit();
}


Анимации появления и исчезновения

calendar_show.xml




    




calendar_hide.xml




    



    


Ответы

Ответ 1



Попробуйте добавить AnimationListener для управления видимостью фрагмента: private void calendarShow() { FragmentTransaction t = getSupportFragmentManager().beginTransaction(); Animation anim = AnimationUtils.loadAnimation(this, R.animator.calendar_show); anim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { //Сделайте фрагмент видимым - setVisibility(VISIBLE); } }); t.startAnimation(anim); t.replace(R.id.calendarView, mCalendar, CALENDAR_TAG); t.show(mCalendar); t.commit(); //Сделайте фрагмент невидимым - setVisibility(GONE); mCalendar.refreshView(); }

Круглый ProgressBar с 4 цветами (неплавный градиент)

#java #android #progress_bar #градиент




Update: залил новый скриншот, от 0 до 165 у нас круг закрашен, прогресс равен ~ 45%,
остальная часть тусклыми цветами

Есть ли возможность сделать progressbar с 4 цветами? По сути это градиент, но вот
только у тэга gradient нет параметров, позволяющих сделать строго разграниченные цвета
(знаю, что в api 24 такое вроде можно сделать, но мне нужно с api 15 и выше). Для прогресса
использую shape ring:


    
        
    



Заранее спасибо.
    


Ответы

Ответ 1



Путаетесь в терминологии - это раздражает многих, но не меня :-) (Просьбы о не плавном градиенте равнозначны мольбам о квадрате но без углов) Видимо вам нужны не градиенты а круговые диаграммы ну а дальше берите любую за основу и изменяйте в нужном вам направлении; присмотритесь например к MPAndroidChart, как вам верно подсказал @pavlofff в комментарии.

Получить изображение из reCAPTCHA

#c_sharp #net #веб_программирование #recaptcha


Мне нужно пройти авторизацию на вебсайте средствами C#. В форме авторизации присутствует
reCAPTCHA. Нужно как то её обработать (т.е. вытащить картинки, текст задания и позволить
пользователю решить это дело).

Для начала, я вижу пустой div class="g-recaptcha" data-sitekey="...". Отсюда можно
взять значение атрибута data-sitekey. Перейдём по ссылке https://www.google.com/recaptcha/api/challenge?k=[data-sitekey
value] и загрузится примерно такая страничка:

var RecaptchaState = {
    challenge : '...',
    server : 'https://www.google.com/recaptcha/api/',
    site : '...',
    ...
};

document.write('');


Каким образом я могу вытащить картинки с reCAPTCHA? Старая reCAPTCHA представлялась
по видимому одной картинкой, которую можно было загрузить по такому адресу: http://www.google.com/recaptcha/api/image?c=[challenge
from RecaptchaState]. Что делать с новой, я не знаю. Не особо разбираюсь в веб-программировании.



UPD: Возможно есть иное решение, при котором нам не потребуется получать картинку.
Может быть возможно как то отобразить капчу, чтобы её прошёл пользователь. Что то вроде
WebBrowser, только не всю страницу, а лишь саму капчу, полученную из WebResponse.
    


Ответы

Ответ 1



Я открываю сайт в WebBrowser, получаю все картинки с сайта и так нахожу саму картинку капчи: private void openAndWaitCompliteURL(string url) { webBrowser.Navigate(url); while (webBrowser.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); } } private string getImageWhenLoad(string attr) { HtmlDocument doc = webBrowser.Document; HtmlElementCollection htmlElementCollection = doc.Images; foreach (HtmlElement htmlElement in htmlElementCollection) { string imgUrl = htmlElement.GetAttribute(attr); return imgUrl; } } openAndWaitCompliteURL(url); capchaForm.capchaPictureBox.ImageLocation = getImageWhenLoad("src"); После чего вывожу картинку в PictureBox.

Как узнать активен ли фрагмент/активити

#java #android #android_fragment #activity #push


В андроид приложении нужно реализовать функциональность чата.
Информация о входящем сообщении приходит через Firebase Push и сохраняется в локальной БД. 

Что хочу: если при приходе push открыта активити (фрагмент чата в MainActivity),
то обновить данные, если открыт другой фрагмент или приложение свернуто - создать и
показать Notification

Основной вопрос: как узнать что в данный момент на экране открыт чат?
Информацию во фрагмент можно отправить sendBroadcast, но как узнать что фрагмент
ее не получил (и в этом случае создать уведомление)?
    


Ответы

Ответ 1



Как вариант в MainActivity сохранять текущий фрагмент. Допустим у вас есть метод для смены фрагментов, получаемый фрагмент держите как переменную активности. public void switchToFragment(Fragment fragment) { getSupportFragmentManager() .beginTransaction() .replace(R.id.frame, fragment) .addToBackStack(null) // что бы не делать стек фрагментов .commitAllowingStateLoss(); currentFragment = fragment; } В данном примере currentFragment и выступает той самой переменной. Далее делайте проверку: if (currentFragment instanceof ChatFragment ) { // ваш код при открытом чате } ChatFrament это название вашего класса фрагмента в котором и реализован чат. Еще видел вот такую реализацию: ChatFrament test = (ChatFrament) getSupportFragmentManager().findFragmentByTag("tag"); if (test != null && test.isVisible()) { // ваш код при открытом чате } В данном примере нужно будет присваивать теги для фрагментов, тогда к ним можно будет обратиться и узнать активен ли он. В таком случае метод для смены фрагментов я бы делал вот так: public void switchToFragment(Fragment fragment, String tag) { getSupportFragmentManager() .beginTransaction() .replace(R.id.frame, fragment, tag) .addToBackStack(null) // что бы не делать стек фрагментов .commitAllowingStateLoss(); }

Получение только измененной части LiveData<List>

#android #observer #livedata


Активно изучаю LiveData в андроид и хотел бы разобраться со следующим вопросом.
Андроид устройство - клиент, через сокет цепляется к серверу. Сервер периодически
присылает какие-то сообщения, среди них есть события, которые необходимо отрисовывать
на вьюшке.
Я использую mvvm паттерн. На события, пришедшие от сокета, подписывается репозиторий:

class EventRepository : IEventRepositoty {

    private companion object {
        val MAX_EVENT = 20
    }
    private val mEventList = MutableLiveData>()
    val eventList : LiveData> = mEventList
    .....
}


В репозитории хранится mEventList, в который я складываю события, пришедшие от сервера.
Вопрос в том, что если ViewModel подпишется на eventList, то при записи нового события
во ViewModel сработает observer, аргументом которого будет весь новый список. Но на
вьюшке уже большая часть списка отрисована, и мне надо только вставить новый item.
Решение, которое пришло в голову: события записывать не в LiveData, а в обычный list,
а в LiveData держать только один EventModel
Но что-то мне не нравится данный вариант, ибо при старте я запрашиваю последние события
с сервера, и их придет список. Есть вариант держать LiveData>,
но писать туда только список новых элементов (если событие одно, то, соответственно,
список размера 1).

Может, есть какой-то более удобный способ получить только измененную часть списка?
    


Ответы

Ответ 1



Если речь идет о RecyclerView, рекомендую вам обратить внимание на новый адаптер ListAdapter из библиотеки поддержки v7. Он обязывает реализовать механизм DiffUtil, который позаботится о вычислении изменений между новыми данными и уже имеющимися в адаптере и автоматически произведет нужные манипуляции (добавит, удалит, изменит соответствующие айтемы). Таким образом вы отдаете адаптеру актуальный список целиком (а не в ручную отбираете новые элементы), он же позаботится о остальном. При этом работать будет все полностью автоматически - при изменении данных в репозитории они будут изменяться и в виджете без каких либо действий с вашей стороны. Пример

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

#javascript #jquery #jquery_ui


Имеется 
на странице. Через js добавили метод .draggable() и обработчик клика. Как отличать эти события и работать с ними не зависимо друг от друга?


Ответы

Ответ 1



Есть различие между mousemove, mousedown и mouseup. Вы можете сделать что-то вроде этого: var flag = 0; var element = document.getElementById('draggable'); $("#draggable").draggable(); element.addEventListener("mousedown", function(){ flag = 0; }, false); element.addEventListener("mousemove", function(){ flag = 1; }, false); element.addEventListener("mouseup", function(){ if(flag === 0){ console.log("click"); } else if(flag === 1){ console.log("drag"); } }, false);
Drag or click me>
Для нубов: это выводится в консоль. И это работает.

Как сделать обрезку краёв фото на сайте?

#html #css #css3


В общем, проблема такая. На сайте пользователи вставляют фотки в дырки. Иногда картинки
выходят за края, как на фото. Как сделать так, чтобы эти края обрезались? Вот думаю,
сделать div с overflow:hidden с координатами и размерами в соответствии с дырками,
но ему надо будет придать форму в соответствии с дырками, как это сделать - не знаю.
Нахождение прозрачных областей на фото уже сделано.

    


Ответы

Ответ 1



Ход мысли у Вас правильный - overflow:hidden;. Но, "нахождение прозрачных областей"... Это вообще законно? ))) window.onload = function() { var oAl = document.querySelector('.photos_wrapper'), oSrs; document.addEventListener('dragstart', function(ev) { oSrs = ev.target.src; }); oAl.addEventListener('dragover', function(ev) { ev.preventDefault(); }); oAl.addEventListener('drop', function(ev) { ev.preventDefault(); if (ev.target.classList.contains('vignette')) { ev.target.style.backgroundImage = `url('${oSrs}')`; let oClear = document.createElement('DIV'); oClear.classList.add('clear'); oClear.innerHTML = '×'; oClear.addEventListener('click', function(ev) { this.parentElement.style.backgroundImage = ''; this.remove(); }); ev.target.appendChild(oClear); } }); } * { box-sizing: border-box; margin: 0; padding: 0; } .photos_wrapper { background: url(https://i.stack.imgur.com/WEjJ0.jpg) -5px -3px no-repeat; height: 439px; margin: 0 auto; position: relative; width: 612px; } .vignette { background: #eff; background: url('https://i.imgur.com/sgsEcPB.jpg') center no-repeat; background-size: cover; border: 2px solid #0cc; box-shadow: 1px 2px 2px #000; overflow: hidden; position: absolute; } .vignette:hover>.clear { visibility: visible; } .style_1 { border-radius: 30%; height: 130px; width: 225px; } .style_2 { border-radius: 50%; height: 106px; width: 148px; } .style_3 { border-radius: 30%; height: 111px; width: 151px; } .style_4 { border-radius: 30%; height: 145px; width: 236px; } .photo_1 { left: 26px; top: 20px; } .photo_2 { left: 358px; top: 20px; } .photo_3 { left: 15px; top: 160px; } .photo_4 { left: 151px; top: 149px; transform: rotate(-19deg); } .photo_5 { left: 307px; top: 149px; transform: rotate(19deg); } .photo_6 { left: 445px; top: 160px; } .photo_7 { left: 22px; top: 275px; } .photo_8 { left: 351px; top: 275px; } .thumbs_wrapper { bottom: 0; display: flex; flex-flow: row nowrap; justify-content: space-around; position: absolute; width: 100%; } .clear { background: #fff; border-radius: 50%; bottom: 4px; cursor: pointer; font: bold 20px/20px 'Arial'; height: 20px; left: calc(50% - 10px); opacity: 0.5; position: absolute; text-align: center; transition: all 0.6s ease; visibility: hidden; width: 20px; } .clear:hover { border-radius: 10%; opacity: 1.0; } .thumbs_wrapper>img { border: 1px solid #eee; box-shadow: 1px 3px 8px #000; height: 30px; width: 40px; } .thumbs_wrapper>img:hover { animation: shake .5s ease infinite; } @keyframes shake { 26% { transform: rotate(-20.0deg); } 76% { transform: rotate(20.0deg); } }


Почему возникает исключение OutOfMemoryError?

#java #сборщик_мусора


Работает пока GC не удалит объект, на который есть только "мягкая" (monkey) ссылка. 

Два вопроса:


Почему иногда вылетает OutOfMemoryError, а иногда нет? Вылетает тогда, когда GC не
справляется со своей работой или я что-то не так понял? 
От чего зависит продолжительность работы программы?


Запускал на 3-х компах по 5-7 раз:


на одном ПК работает ~150сек(всегда вылетает OutOfMemoryError), 
на втором ПК работает по ~450-500сек(иногда не вылетает, OutOfMemoryError),
на третьем ПК работает ~60сек(всегда вылетал OutOfMemoryError).


На всех ПК по 8гб оперативной памяти.

public class Solution {
    public static Helper helper = new Helper();

    public static class Monkey {
        private String name;

        public Monkey(String name) {
            this.name = name;
        }

        @Override
        protected void finalize() {
            Helper.isFinalized = true;
            System.out.format("Bye-Bye, %s!\n", name);
        }
    }

    public static void main(String args[]) throws InterruptedException {
        helper.startTime();

        Monkey monkey = new Monkey("Simka");

        SoftReference reference = new SoftReference<>(monkey);

        helper.callGC();

        monkey = null;

        helper.callGC();
        helper.heapConsuming();

        if (reference.get() == null)
            System.out.println("Finalized");

        helper.finish();
    }

    public static class Helper {
        public static boolean isFinalized;

        private long startTime;

        void startTime() {
            this.startTime = System.currentTimeMillis();
        }

        int getTime() {
            return (int) (System.currentTimeMillis() - startTime) / 1000;
        }

        void callGC() throws InterruptedException {
            System.gc();
            Thread.sleep(1000);
        }

        void heapConsuming() {
            try {
                List heap = new ArrayList(100000);
                while (!isFinalized) {
                    heap.add(new Solution());
                }
            } catch (OutOfMemoryError e) {
                System.out.println("Out of memory error raised");
            }
        }

        public void finish() {
            System.out.println("Done");
            System.out.println("It took " + getTime() + " sec");
        }
    }
}

    


Ответы

Ответ 1



Дюк, вынеси мусор Вот ссылка. Можно прочесть весь цикл статей, про все сборщики мусора, которые предоставляет Java HotSpot VM. Оттуда станет понятно, когда запускается сборщик мусора, как работает, и немного станет яснее о внутреннем устройстве разных GC.

Как организовать синхронизацию потоков?

#c_sharp #net #многопоточность


Есть поток, который в цикле ожидает данные от ком-порта (или любого другого интерфейса)
и при их поступлении вызывает событие OnFrameReceived(...). Мне нужно написать блокирующий
метод SendAndWaitReply(...), который отправит данные по ком-порту и будет ждать ответа
(события OnFrameReceived) или таймаута операции (если ответ не придет).

Подскажите, как организовать синхронизацию потока чтения и потока, отправляющего команду?

public class Device
{
    Connection connection = new Connection(...);

    public Device()
    {
        connection.FrameReceived += Connection_FrameReceived;
    }

    // Отправить пакет и дождаться ответа/таймаута
    public void SendAndWaitReply(ITxFrame frame)
    {
        bool timeout = false;

        // Отправить пакет и заблокировать поток до наступления таймаута или приема
ответа

        if(timeout)
        {
            throw new TimeoutException();    
        }
    }

    // Событие приема пакета
    private void Connection_FrameReceived(object sender, RxFrame frame)
    {
        // Разблокировать поток, ожидающий приема пакета

        // Обработка принятого пакета
    }
}

    


Ответы

Ответ 1



Не знаю, можно ли проще: public class Device { private object _sendAndWaitReplySyncObject = new object(); private AutoResetEvent _frameReceivedEvent = new AutoResetEvent(false); private AutoResetEvent _frameAcceptedEvent = new AutoResetEvent(false); private AutoResetEvent _timeoutEvent = new AutoResetEvent(false); private ManualResetEvent _outsideSendAndWaitReplyEvent = new ManualResetEvent(true); // Отправить пакет и дождаться ответа/таймаута public void SendAndWaitReply(object frame) { try { lock (_sendAndWaitReplySyncObject) { // переводим все эвенты в not signaled состояние _outsideSendAndWaitReplyEvent.Reset(); _frameReceivedEvent.Reset(); _frameAcceptedEvent.Reset(); _timeoutEvent.Reset(); // Отправить пакет bool timeout = !_frameReceivedEvent.WaitOne(3000); if (timeout) { _timeoutEvent.Set(); // для того, что бы блок finally не сработал раньше времени _frameReceivedEvent.WaitOne(); throw new TimeoutException(); } else { _frameAcceptedEvent.Set(); // для того, что бы блок finally не сработал раньше времени _frameReceivedEvent.WaitOne(); } } } finally { // что бы Connection_FrameReceived не ждал вечно на вызове WaitAll _outsideSendAndWaitReplyEvent.Set(); } } // Событие приема пакета private void Connection_FrameReceived(object sender, object frame) { _frameReceivedEvent.Set(); // Разблокировать поток, ожидающий приема пакета int index = WaitHandle.WaitAny(new WaitHandle[] { _outsideSendAndWaitReplyEvent, _frameAcceptedEvent, _timeoutEvent }); switch (index) { case 0: // событие сработало вне метода SendAndWaitReply break; case 1: _frameReceivedEvent.Set(); // Обработка принятого пакета break; case 2: _frameReceivedEvent.Set(); // сработал _timeoutEvent break; } } }

Объединить объекты в массиве по заданному признаку

#javascript #массивы


Имеется массив из объектов. как можно объединить несколько из них, если у них есть
один общий признак (одинаковое свойство)?
К примеру есть массив:

[
  {
      "Text": "Прочие дебиторы",
      "Value": "237528"
  },
  {
      "Text": "=",
      "Operation": true
  },
  {
      "Text": "(",
      "Operation": true
  }
];


У двух элементов массива есть одно общее свойство Operaion: true.
на выходе нужно получить:

[
  {
      "Text": "Прочие дебиторы",
      "Value": "237528"
  },
  {
      "Text": "=(",
      "Operation": true
  }
]

    


Ответы

Ответ 1



var arr = [ {'Text': 'Прочие дебиторы', 'Value': '237528'}, {'Text': '=', 'Operation': true}, {'Text': '(','Operation': true} ]; var data = arr.filter(t => t['Operation'] !== true); data.push( { 'Text': arr.map(e => e['Operation'] === true ? e['Text'] : '').join(''), 'Operation': true } ); console.log(data);

mousewheel smooth scroll с анимацией фигур

#javascript #jquery #scroll


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



var rellax = new Rellax('.rellax', {
  center: false,
  wrapper: null,
  round: true,
  vertical: true,
  horizontal: false
});


// TweenMax
$(function() {

  var $window = $(window); //Window object

  var scrollTime = 1.2; //Scroll time
  var scrollDistance = 170; //Distance. Use smaller value for shorter scroll and
greater value for longer scroll

  $window.on("mousewheel DOMMouseScroll", function(event) {

    event.preventDefault();

    var delta = event.originalEvent.wheelDelta / 120 || -event.originalEvent.detail / 3;
    var scrollTop = $window.scrollTop();
    var finalScroll = scrollTop - parseInt(delta * scrollDistance);

    //console.log(finalScroll);

    $('.leaf>img').css({
      'transform': 'rotateX(0deg)'
    });
    //$('.leaf>img').removeClass('rotate');

    TweenMax.to($window, scrollTime, {
      scrollTo: {
        y: finalScroll,
        autoKill: true
      },
      ease: Power1.easeOut,
      autoKill: true,
      overwrite: 5,
      onComplete: function() {
        $('.leaf>img').css({
          'transform': 'rotateX(50deg)'
        });
        //$('.leaf').addClass('rotate');
      }
    });

  });

});

// MouseWheel
// if (window.addEventListener) window.addEventListener('DOMMouseScroll', wheel, false);
// window.onmousewheel = document.onmousewheel = wheel;

// function wheel(event) {
//     var delta = 0;
//     if (event.wheelDelta) delta = event.wheelDelta / 220;
//     else if (event.detail) delta = -event.detail / 3;

//     handle(delta);
//     if (event.preventDefault) event.preventDefault();
//     event.returnValue = false;
// }

// var goUp = true;
// var end = null;
// var interval = null;

// function handle(delta) {
// 	var animationInterval = 20; //lower is faster
//     var scrollSpeed = 20; //lower is faster

// 	if (end == null) {
//   	end = $(window).scrollTop();
//   }
//   end -= 20 * delta;
//   goUp = delta > 0;

//   if (interval == null) {
//     interval = setInterval(function () {
//       var scrollTop = $(window).scrollTop();
//       var step = Math.round((end - scrollTop) / scrollSpeed);
//       if (scrollTop <= 0 || 
//           scrollTop >= $(window).prop("scrollHeight") - $(window).height() ||
//           goUp && step > -1 || 
//           !goUp && step < 1 ) {
//         clearInterval(interval);
//         interval = null;
//         end = null;
//       }
//       $(window).scrollTop(scrollTop + step );
//     }, animationInterval);
//   }
// }
* {
  box-sizing: border-box;
}

html,
body {
  padding: 0;
  margin: 0;
  font-family: sans-serif;
  font-size: 20px;
  line-height: 2rem;
  position: relative;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
  transform-origin: 50% 50%;
  transform-style: preserve-3d;
  transition: all .5s ease-in-out;
}

main {
  padding: 2rem 3rem;
  text-align: center;
}

.leaf {
  display: block;
  user-select: none;
  font-size: 0;
  visibility: visible;
  opacity: 1;
  width: 20vw;
  -webkit-perspective: 500px;
  perspective: 500px;
}


/* .rotate {
  animation: rotate 1s ease-in-out;
}


@keyframes rotate {
  from { transform: rotateX(0deg); }
  50% {transform: rotateX(50deg);}
  to { transform: rotateX(0deg); }
} */

.l-2 {
  margin-left: 30%;
}

.l-3 {
  margin-left: 70%;
}

header {
  position: fixed;
  z-index: 2;
  width: 100%;
  height: auto;
  margin-top: -10%;
  -webkit-perspective: 500px;
  perspective: 500px;
}






Smooth Scroll

Use your mousewheel to scroll

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur natus, facere nulla similique doloremque! Ullam voluptatem debitis esse. Deleniti quas, vel ad consectetur facilis ab consequatur voluptate aut optio odit nisi reprehenderit sint, ipsa incidunt itaque id voluptatum repudiandae alias esse velit quo voluptatibus recusandae earum eligendi! Est, quae, aliquam?

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptas, earum ullam hic id! Corporis cupiditate, voluptatibus eligendi suscipit ratione eos, sequi aperiam voluptatem laboriosam! Debitis consectetur eum aperiam similique ullam dolore, labore porro, sequi fuga atque, tempora, est delectus veniam! Ad tempora, voluptas cupiditate praesentium illo iure. Cupiditate, necessitatibus natus id eius nulla ab suscipit tempora nisi itaque omnis quas, voluptates accusantium cum labore nam. Laboriosam alias doloremque quos adipisci pariatur ipsum doloribus et cupiditate omnis cum, ducimus deleniti, sequi optio harum! Iste quas in, qui nobis voluptatibus quibusdam doloremque culpa, numquam officia incidunt, quidem! Asperiores omnis amet incidunt eveniet.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium animi sint officiis, voluptate nam vitae inventore minus aliquid temporibus soluta natus, qui repellendus ducimus eum veritatis neque impedit odio quibusdam.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur natus, facere nulla similique doloremque! Ullam voluptatem debitis esse. Deleniti quas, vel ad consectetur facilis ab consequatur voluptate aut optio odit nisi reprehenderit sint, ipsa incidunt itaque id voluptatum repudiandae alias esse velit quo voluptatibus recusandae earum eligendi! Est, quae, aliquam?

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptas, earum ullam hic id! Corporis cupiditate, voluptatibus eligendi suscipit ratione eos, sequi aperiam voluptatem laboriosam! Debitis consectetur eum aperiam similique ullam dolore, labore porro, sequi fuga atque, tempora, est delectus veniam! Ad tempora, voluptas cupiditate praesentium illo iure. Cupiditate, necessitatibus natus id eius nulla ab suscipit tempora nisi itaque omnis quas, voluptates accusantium cum labore nam. Laboriosam alias doloremque quos adipisci pariatur ipsum doloribus et cupiditate omnis cum, ducimus deleniti, sequi optio harum! Iste quas in, qui nobis voluptatibus quibusdam doloremque culpa, numquam officia incidunt, quidem! Asperiores omnis amet incidunt eveniet.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium animi sint officiis, voluptate nam vitae inventore minus aliquid temporibus soluta natus, qui repellendus ducimus eum veritatis neque impedit odio quibusdam.

Страничка с плавным скроллом. Листочки с parallax эффектом. Для плавного скролла пытаюсь использовать или mousewheel или вот рабочий вариант с tweenMax (пока не могу выбрать какой вариант лучше). При параллаксе листочков динамически генерируется необходимый transform:translate3d(...). Хотелось бы чтобы при остановке скролла анимация поворота листочка начиналась как-то только остановили скроллить колесико (в этот момент еще неторое время стр. скроллится сама по анимации). Пример brontidebg.com, все то же самое хотелось бы, но намного проще с jquery. Вопрос: Как начать анимацию листиков (поворот rotateX(...) сразу после окончания скролла колесиком мыши, т.е. чтобы поворот фигуры совпадал с "доскролливанием" (по анимации) стр. ? Получается какое-нибудь событие за секунду до onComplete.


Ответы

Ответ 1



Получилось реализовать подобный эффект с помощью jquery.parallax-scroll function elements () { $('.element1 img').css('opacity', 0).one('inview', function(isInView) { if (isInView) {$(this).addClass('animated fadeInRight delayp7');} }); $('.element2 img').css('opacity', 0).one('inview', function(isInView) { if (isInView) {$(this).addClass('animated fadeInRight delayp8');} }); } elements(); $(window).scroll(function () { var ww = $(window).width(); elements(); }); img { max-width: 100%; } .element { position: absolute; left: 50%; } .element.element2 { width: 85px; margin-left: 34px; top: 54px; } .element.element4 { width: 85px; margin-left: -154px; top: 24px; } .element.element1 { width: 100px; margin-left: -69px; top: 72px; } section { position: relative; min-height: 1500px; } .animated { -webkit-animation-duration: 1s; animation-duration: 1s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .delayp7 { -webkit-animation-delay: 1.2s; animation-delay: 1.2s; -webkit-animation-duration: 1s; } .delayp8 { -webkit-animation-delay: 1.4s; animation-delay: 1.4s; -webkit-animation-duration: 1s; }


Зачем выделять память для переменных в стеке?

#cpp #стек


В теме еще разбираюсь плохо так что прошу строго не судить.

Насколько я понял, стек в основном нужен для правильного последовательного распределения
выполнения функций в программе. Его вместимость ограничена и он может быть переполнен
тем самым вызвав ошибку. Ввиду этого у меня возник вопрос: Почему бы чтобы уменьшить
заполненность стека по дефолту не кидать все переменные в кучу?

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


Ответы

Ответ 1



Локальные переменные размещаются в стеке, чтобы быть локальными не только для функции, но и для каждой итерации ее вызова. Когда функция запускает сама себя рекурсивно, она должна получить новый блок памяти под локальные переменные, а при возврате первая должна обратно вернуть свои. И единственное что с точки зрения процессора отличает эти два "экземпляра" функции - указатель базы стека. Если у вас локальные переменные суммарно хранят большой объем данных (от сотни килобайт и выше), то имеет смысл выделять область в куче, и хранить указатель на нее в стеке. Почему такой механизм не применяется по умолчанию - потому что это медленнее и в 99% случаев не нужно.

Отношение один к разным типам объектов

#java #c_sharp #sql #entity_framework #архитектура


Я не знаю, есть ли какой-то готовый термин, поэтому в заголовок вынес "один-к-разным-типам-объектов",
но это не термин из EF-диаграмм (один-ко-многим, многие-ко-многим и т.п.)

Вот с какой задачей на архитектуру я столкнулся. Меня интересует каким образом можно
выразить (в первую очередь на слое реляционном, во вторую - на уровне классов) отношение
один-к-разным типам объектов.

Пример из практики, несколько упрощённый. В базе данных существует таблица денежных
переводов (MoneyTransfers) между пользователями сайта с полями:


идентификатор перевода MoneyTransferId,
участник-отправитель SourceUserId,
участник-получатель DestinationUserId,
величина перевода AmountRur.


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

И вот для учёта кто за что кому когда платил (а бардак там бывает знатный, особенно
на какую-нибудь чёрную пятницу) сделана ещё одна таблица, OrderEntries:


идентификатор OrderEntryId,
сумма AmountRur,
идентификатор перевода MoneyTransferId,
идентификатор заказа OrderId.


Т.е. фактически это связь многие-ко-многим между Order и MoneyTransfer с промежуточной
таблицей. Удобно в практике: можно оплатить заказ несколькими переводами, можно одним
переводом оплатить сразу несколько заказов - и по всему этому удобно строить отчёты.

Проблема появляется, когда помимо заказов-закупок девочки захотели продавать друг
другу лачки. Вот тут и появилась вторая таблица в дополнение к Orders — таблица сделок
(Opportunitites), а с ней появилась и проблема, вынесенная в заголовок.

Таблиц у меня две, при этом в OrderEntries мне нужно указать к чему относится эта
запись - к Order или к Opprtunity.

Как быть?

Можно пойти по пути объединения таблиц Order и Opportunity в одну сущность. При этом
допустим такая ORM как Entity Framework предлагает три варианта для хранения данных:
Table Per Hierarchy, Table Per Type и Table Per Concrete Type. Причём все способы имеют
значительные недостатки, либо в удобстве работе, либо с производительностью.

Можно пойти по пути создания на таблице OrderEntry двух полей EntityType и EntityId.
При этом поле EntityType будет иметь низкую селективность, а проконтролировать ограничение
EntityId как внешнего ключа я вообще не представляю себе как.

Другой вариант - сделать на таблице OrderEntry два nullable столбца - один OrderId,
другой OpportunityId и заполнять либо тот, либо другой. Ну, неплохой вариант как кажется.

И последнее, что приходит в голову - это сделать две разных таблицы OrderEntiry -
одна будет OrderEntryForOrder, другая - OrderEntryForOpportunity. Тоже вариант, который
мне нравится, но меньше чем предыдущий: как мне кажется будет сложнее писать запросы
к базе.

Кажется, я перебрал все возможные варианты, ничего не упустил? (Если знаете другой
- напишите)

Меня интересуют какой-то типовой подход (best practice) к решению подобной задачи,
какой вариант более удобен в реальных системах.
    


Ответы

Ответ 1



Можно пойти по пути создания на таблице OrderEntry двух полей EntityType и EntityId. При этом поле EntityType будет иметь низкую селективность, а проконтролировать ограничение EntityId как внешнего ключа я вообще не представляю себе как. Встречал на практике вот этот вариант и он был очень даже работоспособен. Проверка целостности в этом случае, естественно, осуществляется уже не на уровне БД. Индекс должен быть композитный - сразу по двум полям. Другой вариант - сделать на таблице OrderEntry два nullable столбца - один OrderId, другой OpportunityId и заполнять либо тот, либо другой. Ну, неплохой вариант как кажется. Он не масштабируется. В тех системах, с которыми я работал - количество таких таблиц со временем увеличивалось до 20-30. И последнее, что приходит в голову - это сделать две разных таблицы OrderEntiry - одна будет OrderEntryForOrder, другая - OrderEntryForOpportunity. Тоже вариант, который мне нравится, но меньше чем предыдущий: как мне кажется будет сложнее писать запросы к базе. Аналогично.

Контейнеры map/set и кэш процессора

#cpp #оптимизация #stl #cpp17


В книге Артур О'Двайр "Осваиваем C++17 STL"



на стр.104 наткнулся на удивительное заявление:


  Мудрость, накопленная в пост-C++11 мире, гласит, что std::map и
  std::set, будучи основанными на деревьях указателей, настолько
  недружественные к кешу процессора, что их всегда желательно избегать и
  взамен использовать std::unordered_map и std::unordered_set.


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


Ответы

Ответ 1



При однократном поиске в хэш-таблице без синонимов будет прочитано 2 линии кэша (если так получилось, что данные по выравниванию не поместились в одну линию, то 3 линии кэша), а для дерева очевидно, что больше, особенно если в узлах дерева хранятся указатели на ключи (а не сами ключи). Если поисков много, активность (в смысле количества активных процессов в системе, которые будут "вымывать" ваши данные из кэша) низкая, то искомые данные для обеих структур окажутся в кэше и повторные поиски будут быстрее. Но и здесь, очевидно, что хэш-таблица будет быстрее. Интересно, что для маленького дерева, которое вместе с данными (ключами) размещается в 2-х последовательных линиях кэша (128 байт, последовательно размещенными в памяти с адреса, кратного 64) даже 4 обращения к памяти (корень, ключ в корне, потомок, его ключ) могут занять меньше времени, чем 2 обращения к памяти для хэш-таблицы (там наверняка указатель из таблицы и данные будут сильно разнесены по адресам), поскольку ОС может устанавливить политику доступа к кэшу для опережающего последовательного чтения линий кэша.

C++ Как в Linux мониторить usb устройства?

#cpp #linux #gtk


У меня есть графическое GTK приложение и мне нужно получать информацию об подключенных
USB девайсах, используя libusb я могу получить то что нужно но как оформить сам мониторинг,
правильно ли запускать в отдельном потоке вечный цикл и обновлять поток UI? Мне интересно
каким образом работают такие системы, какие есть модели управления потоками, возможно
есть какие-нибудь механизмы взаимодействия с системой так как программа работает в
user space, system calls? 


  Можно ли чтобы Linux пробудил мой поток когда подключили новый девайс?

    


Ответы

Ответ 1



Для начала поставить библиотеку libudev sudo apt-get install libudev-dev Код отсюда #include #include #include int main() { struct udev *udev; struct udev_device *dev; struct udev_monitor *mon; int fd; int status; /* create udev object */ udev = udev_new(); if (!udev) { fprintf(stderr, "Can't create udev\n"); return 1; } //группы сообщений //(1)kernel - посылает событие к udevd в момент подключения устройства для его инициализации //(2)udev - посылает событие в userspace программам, используемым libudev mon = udev_monitor_new_from_netlink(udev, "udev"); //Можно также добавлять подсистемы pci, usb, scsi, scsi_host, scsi_generic //Типы устройств usb_device, usb_interface, scsi_host, scsi_device, disk, partition udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "disk"); //флешки udev_monitor_enable_receiving(mon); fd = udev_monitor_get_fd(mon); printf("Start...\n"); fflush(stdout); while (1) { fd_set fds; struct timeval tv; int ret; FD_ZERO(&fds); FD_SET(fd, &fds); tv.tv_sec = 0; tv.tv_usec = 0; ret = select(fd+1, &fds, NULL, NULL, &tv); if (ret > 0 && FD_ISSET(fd, &fds)) { dev = udev_monitor_receive_device(mon); if (dev) { printf("I: ACTION=%s\n", udev_device_get_action(dev)); printf("I: DEVNAME=%s\n", udev_device_get_sysname(dev)); printf("I: DEVPATH=%s\n", udev_device_get_devpath(dev)); printf("I: MACADDR=%s\n", udev_device_get_sysattr_value(dev, "address")); printf("---\n"); fflush(stdout); /* free dev */ udev_device_unref(dev); } } /* 500 milliseconds */ usleep(500*1000); } /* free udev */ udev_unref(udev); return 0; } Событие uevent, которое udevd получает от драйвера ядра - это GROUP_KERNEL (1), а уведомление программ из пространства пользователя /lib/udev programs or others - это GROUP_UDEV (2). Workflow отсюда По поводу взаимодействия, я бы форкул цикл ожидания событий монитора и при инициализации нового устройства посылал родительскому процессу сигналы (сигналы реального времени, чтоб устройство не потерять при подключении, т.к. эти сигналы ставятся в очередь). Поправьте если не прав. #include #include #include #include #include #include void task() { printf("Create thread and join my func"); auto func = []() { for(auto i = 0 ; i<3 ; ++i) { sleep(1); printf("Hard calculations: %d ", i); } fflush(stdout); }; std::thread t(func); t.join(); } int main() { struct udev *udev; struct udev_device *dev; struct udev_monitor *mon; int fd; int status; /* create udev object */ udev = udev_new(); if (!udev) { fprintf(stderr, "Can't create udev\n"); return 1; } pid_t pid = fork(); switch (pid) { case -1: exit(EXIT_FAILURE); /*Ошибко*/ case 0: { /*Выполнение дочернего процесса*/ //группы сообщений //kernel - посылает событие к udevd в момент подключения устройства для его инициализации //udev - посылает событие в userspace программам, используемым libudev mon = udev_monitor_new_from_netlink(udev, "udev"); //Можно также добавлять подсистемы pci, usb, scsi, scsi_host, scsi_generic //Типы устройств usb_device, usb_interface, scsi_host, scsi_device, disk, partition udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "disk"); //флешки udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_device"); //флешки udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_interface"); //флешки udev_monitor_enable_receiving(mon); fd = udev_monitor_get_fd(mon); printf("Start...\n"); fflush(stdout); while (1) { fd_set fds; int ret; FD_ZERO(&fds); FD_SET(fd, &fds); ret = select(fd+1, &fds, nullptr, nullptr, nullptr); if (ret > 0 && FD_ISSET(fd, &fds)) { dev = udev_monitor_receive_device(mon); if (dev) { printf("I: ACTION=%s\n", udev_device_get_action(dev)); printf("I: DEVNAME=%s\n", udev_device_get_sysname(dev)); printf("I: DEVPATH=%s\n", udev_device_get_devpath(dev)); printf("I: MACADDR=%s\n", udev_device_get_sysattr_value(dev, "address")); printf("---\n"); fflush(stdout); if(strncmp(udev_device_get_action(dev), "add", 3) == 0) { union sigval value; value.sival_int = 1; sigqueue(getppid(), SIGRTMIN, value); } /* free dev */ udev_device_unref(dev); } } /* 500 milliseconds */ usleep(500*1000); } /* free udev */ udev_unref(udev); } default: { /*Продолжение выполнения родительского процесса*/ int ex; int sig; siginfo_t si; sigset_t allSigs; sigfillset(&allSigs); if(sigprocmask(SIG_SETMASK, &allSigs, NULL) == -1) { printf("fail\n"); exit(EXIT_FAILURE); } while(1) { sig = sigwaitinfo(&allSigs, &si); printf("sig %s\n",strsignal(sig)); if(SIGINT == sig || SIGTERM == sig) { kill(pid, SIGTERM); exit(EXIT_SUCCESS); } if(SIGRTMIN == sig) { task(); /*Запускаем функцию, где реализуем отдельный поток*/ } } } } //switch return 0; }

Принадлежность каждой клетки к многоугольнику

#cpp


У меня есть многоугольник, точнее координаты его вершин, я его как будто накладываю
на клетчатую бумагу, так, что он делиться на клеточки. Поскольку он у меня не ложиться
точь-в-точь по клеточкам, то он будет их пересекать. Я ищу площадь каждой клетки, лежащей,
хотя бы частично, в многоугольнике. Итогом программы должна быть матрица, элементами
которой будут площади каждой клетки. Скажу на всякий случай, все клетки одного размера,
а площадь клетки - это площадь той части клетки, которая находится внутри многоугольника.

#include "pch.h"
#include 
#include 
#include 
#include 
#include  
#include 
using namespace std;
struct flat_vector
{
    double x;
    double y;
};

double angle(flat_vector xy1, flat_vector xy2) {
    return xy1.x * xy2.y - xy2.x*xy1.y;
}

flat_vector max(flat_vector& pxy1, flat_vector& pxy2) {
    if (pxy1.x >= pxy2.x && pxy1.y >= pxy2.y) {
        return flat_vector{
            pxy1.x, pxy1.y
        };
    }
    else if (pxy1.x >= pxy2.x && pxy1.y <= pxy2.y) {
        return flat_vector{
            pxy1.x,pxy2.y
        };
    }
    else if (pxy1.x <= pxy2.x && pxy1.y <= pxy2.y) {
        return flat_vector{
            pxy2.x, pxy2.y
        };
    }
    else {
        return flat_vector{
            pxy2.x, pxy1.y
        };
    }
}
flat_vector min(flat_vector& pxy1, flat_vector& pxy2) {
    if (pxy1.x >= pxy2.x && pxy1.y >= pxy2.y) {
        return flat_vector{
            pxy2.x, pxy2.y
        };
    }
    else if (pxy1.x >= pxy2.x && pxy1.y <= pxy2.y) {
        return flat_vector{
            pxy2.x,pxy1.y
        };
    }
    else if (pxy1.x <= pxy2.x && pxy1.y <= pxy2.y) {
        return flat_vector{
            pxy1.x, pxy1.y
        };
    }
    else {
        return flat_vector{
            pxy1.x, pxy2.y
        };
    }
}
flat_vector pere(flat_vector& xyp1, flat_vector& xyp2, flat_vector& pxy1, flat_vector&
pxy2) {
    double eps = 0.001;
    double z = ((xyp1.x - xyp2.x)*(pxy1.y - pxy2.y) - (xyp1.y - xyp2.y)*(pxy1.x -
pxy2.x));
    double q = ((xyp1.x*xyp2.y - xyp1.y * xyp2.x)*(pxy1.x - pxy2.x) - (xyp1.x - xyp2.x)*(pxy1.x*pxy2.y
- pxy1.y * pxy2.x)) / z;
    double e = ((xyp1.x*xyp2.y - xyp1.y * xyp2.x)*(pxy1.y - pxy2.y) - (xyp1.y - xyp2.y)*(pxy1.x*pxy2.y
- pxy1.y * pxy2.x)) / z;
    if (abs(z) >= eps) {
        return flat_vector{
            q,
            e
        };
    }
    else {
        return flat_vector{
            NULL,NULL
        };
    }
}


double are(vector& xyp, vector& pxy) {

    //vector xyp{ {0,0},{2,0},{5,1}, {4,4},{2,4} };// координаты многоугольника
    double n = xyp.size();
    //vector pxy{ {4,0.5},{5,0.5},{5,1.5},{4,1.5} };//координаты клетки
    double b = pxy.size();
    xyp.push_back(xyp[0]);
    pxy.push_back(pxy[0]);
    flat_vector nu{ NULL,NULL };
    vector xxyy;
    vector lxy;
    int k = 0;
    int m = 0;

    for (int i = 0; i < n; i++) {
        //cout << "Точки пересечения " << i + 1 << "-й вершины многоугольника с пикселем"
<< endl;
        //cout << "----------------------------------------------------------" << endl;
        for (int j = 0; j < b; j++) {
            xxyy.push_back(pere(xyp[i], xyp[i + 1], pxy[j], pxy[j + 1]));
            if (xxyy[k] != nu) {
                if (xxyy[k] < max(pxy[j], pxy[j + 1]) && xxyy[k] > min(pxy[j], pxy[j
+ 1])) {
                    lxy.push_back(xxyy[k]);
                    //cout << lxy[m] << endl;
                    m++;
                }
            }
            k++;
        }
    }

    vector xxy;
    vector x_y;
    double *ug;
    int s = 0;
    int l = 0;
    int full = 0;
    ug = new double[n];
    for (int j = 0; j < b; j++) { //определяю какие точки клетки лежат в многоугольнике
        for (int i = 0; i < n; i++) {
            xxy.push_back(pxy[j] - xyp[i]);
            x_y.push_back(xyp[i + 1] - pxy[j]);
        }
        for (int i = 0; i < n; i++) {
            ug[i] = angle(xxy[l], x_y[l]);
            l++;
            if (ug[i] > 0) {
                s = 1;
            }
        }
        //cout << "Точка " << pxy[j];
        if (s == 0) {
            lxy.push_back(pxy[j]);
            //cout << " внутри" << endl;
            full++;
            m++;
        }
        else
        {
            //cout << ") снаружи" << endl;
        }
        s = 0;
    }
    foo(lxy);
    sort(lxy);
    //lxy.push_back(lxy[0]);
    m = lxy.size();
    double *ar;
    ar = new double[m];
    double area = 0;
    for (int i = 0; i < m; i++) {
        //cout << lxy[i] << endl;
    }
    for (int i = 0; i < m - 1; i++) {
        ar[i] = angle(lxy[i], lxy[i + 1]);
        area += ar[i];
    }
    area /= 2;
    if (full == 4) {//если все 4 вершины пикселя лежат в мн-ке, то площадь клетки
автоматически равна 1
        area = 1;
    }
    else {
        area = abs(area);
    }
    //cout << area << endl;
    return area;
}
double Max(double& x, double& y) {
    if (x >= y) {
        return x;
    }
    else {
        return y;
    }
}
double Min(double& x, double& y) {
    if (x >= y) {
        return y;
    }
    else {
        return x;
    }
}
int main()
{
    //double x_data[4] = { 3.6,5.4,1.9,0.1 };//координаты многоугольника
    //double y_data[4] = { 0.2,1.2,7.3,6.3 };
    vector xy_data = { {3.6,0.2},{5.4,1.2},{1.9,7.3},{0.1,6.3} };
    //int shear_vector_x=6; //вектор сдвига
    //int shear_vector_y=1;
    flat_vector shear_vector = { 6,1 };
    int num_steps = 20;//количество шагов
    flat_vector D_shear_vector = shear_vector / num_steps;
    int numel = 4;//количество вершин многоугольника
    double x_max = 5.4;//крайние точки
    double y_max = 7.3;
    double x_min = 0.1;
    double y_min = 0.2;
    x_max = x_max - x_min;
    y_max = y_max - y_min;
    double nx = ceil(x_max);//количество столбцов матрицы
    double my = ceil(y_max);//количество строк
    double nu = 0;//это нужно, чтобы лишний раз Max и Min не переделывать с типами
    double pix_matr[6][8];//матрица в которую записывается площадь клетки, принадлежащей
многоугольнику, то бишь от 0 до 1
    pix_matr[0][0] = 0;
    double area;
    double background = 0.01;
    double contrast = 0.7;
    double target = background * (1 + contrast) / (1 - contrast);
    for (int t = 0; t < +num_steps; t++) {
        for (int p = 0; p < numel; p++) {
            x_max += shear_vector.x; //сдвигаем по х
            x_min = floor(x_min);
            x_min = Max(nu, x_min);
            x_max = ceil(x_max);
            nu = nx - 1;
            x_max = Min(x_max, nu);
            y_max += shear_vector.y;//сдвигаем по у
            y_min = floor(y_min);
            nu = 0;
            y_min = Max(nu, y_min);
            for (int iy = 0; iy < my; iy++) {
                cout << endl;
                for (int jx = 0; jx < nx; jx++) {
                    // (iy, jx) = координаты ЛЕВОГО НИЖНЕГО угла ЯЧЕЙКИ с
                    //клеткой, соответствующие индексам массива(iy + 1, jx + 1)
                    if (y_min <= iy && iy <= y_max && x_min <= jx && jx <= x_max)
{//проверяем, проецируется ли многоугольник на клетку хотя бы частично
                        double jjx = jx;
                        double iiy = iy;
                        vector pxy = { {jjx,iiy},{jjx + 1,iiy}, {jjx
+ 1,iiy + 1}, {jjx,iiy + 1} };
                        area = are(xy_data, pxy); 
                        pix_matr[iy + 1][jx + 1] = pix_matr[iy + 1][jx + 1] + area
* target + (1 - area)*background;

                    }
                    else {
                        pix_matr[iy + 1][jx + 1] = pix_matr[iy + 1][jx + 1] + background;
                    }
                    cout << pix_matr[iy + 1][jx + 1] << " ";
                }
            }
        }

        move(xy_data, D_shear_vector);
    }
    return 0;
}


Я не прошу смотреть весь код полностью, скажу, что ошибка у меня в 362 строке  area
= are(xy_data, pxy);
Я совместила 2 кода в один, и функция are, которая ищет площадь, была mainом в другом
коде. Я пока новичок и не придумала ничего умнее. Можно ли так создавать функции и
как поступить?

UPD: Поправила код, теперь выводит матрицу с площадями, только часть из них не верные

    #include "pch.h"
#include 
#include 
#include 
#include 
#include 
using namespace std;
struct flat_vector
{
    double x;
    double y;
};
....
int main()
{
    locale::global(locale(""));
    vector xyp{ {0,0},{2,0},{5,1}, {4,4},{2,4} };// координаты многоугольника
    int n = xyp.size();
    vector pxy{ {0,0},{1,0},{1,1},{0,1} };//координаты пикселя
    double b = pxy.size();
    xyp.push_back(xyp[0]);
    pxy.push_back(pxy[0]);
    flat_vector nu{ std::nan(""),std::nan("") };
    vector xxyy;
    int m = 0;
    int s = 0;
    int l = 0;
    int k = 0;
    double are[5][4];
    double area;
    for (int q = 0; q < 4; q++) {//столбцы
        for (int a = 0; a < 5; a++) {//строки
            vector lxy;//сюда записываем вершины клетки и точки пересечения
клетки и многоугольника
            for (int i = 0; i < n; i++) {//программа поиска точек пересечения, работает
правильно
                for (int j = 0; j < b; j++) {
                    xxyy.push_back(pere(xyp[i], xyp[i + 1], pxy[j], pxy[j + 1]));
                    if (xxyy[k] != nu) {
                        if (xxyy[k] < max(pxy[j], pxy[j + 1]) && xxyy[k] > min(pxy[j],
pxy[j + 1])) {
                            lxy.push_back(xxyy[k]);
                            //cout << lxy[m] << endl;
                            //m++;
                        }
                    }
                    k++;
                }
            }
            double *ug;//с помощью данного элемента будем проверять положительность угла
            ug = new double[n];
            int full = 0; //переменная, если будет равняться 4 (т.е. все вершины
клетки принадлежат мн-ку), то площадь равна 1
            l = 0;//счётчик отрезков, которые представлены ниже
            //Данные 2 вектора предназначены для того, чтобы проверять углы между
отрезками от точки (вершины клетки) до двух соседних сторон
            //Не буду много тут объяснять, потому что циклы ниже работают правильно
            vector xxy;//отрезок от
            vector x_y;
            for (int j = 0; j < b; j++) { //определяю какие точки пикселя лежат в
многоугольнике
                for (int i = 0; i < n; i++) {
                    xxy.push_back(pxy[j] - xyp[i]);
                    x_y.push_back(xyp[i + 1] - pxy[j]);
                }
                for (int i = 0; i < n; i++) {
                    ug[i] = angle(xxy[l], x_y[l]);
                    l++;
                    if (ug[i] > 0) {
                        s = 1;
                    }
                }
                //cout << "Точка " << pxy[j];
                if (s == 0) {
                    lxy.push_back(pxy[j]);
                    //cout << " внутри" << endl;
                    full++;
                }
                //else
                //{
                    //cout << ") снаружи" << endl;
                //}
                s = 0;
            }
            foo(lxy);//удаляем повторяющиеся координаты
            sort(lxy);//выстраиваем оставшиеся координаты последовательно
            lxy.push_back(lxy[0]);
            m = lxy.size();
            double *ar;//вспомогательный массив для нахождения площади
            ar = new double[m];
            area = 0;
            //for (int i = 0; i < m; i++) {
            //          cout << lxy[i] << endl;//этот цикл производит все точки клетки,
которые принадлежат многоугольнику
            //}
            for (int i = 0; i < m - 1; i++) {
                ar[i] = angle(lxy[i], lxy[i + 1]);
                area += ar[i];
            }
            area /= 2;//площадь
            if (full == 4) {//если все 4 вершины пикселя лежат в мн-ке, то площадь
пикселя автоматически равна 1
                area = 1;
            }
            else {
                area = abs(area);
            }
            are[a][q] = area;//записываем площадь всех клеток в матрицу
            cout << are[a][q] << " ";
            move(pxy, { 1,0 });//сдвигаем, чтобы перейти к следующей клетки справа
        }
        cout << endl;
        move(pxy, { -5,1 });//поскольку ряд проработан, переходим на строчку выше
    }
    return 0;
}


UPD2: проблема была в этой строке

if (xxyy[k] < max(pxy[j], pxy[j + 1]) && xxyy[k] > min(pxy[j], pxy[j + 1])){


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

    if (xxyy[k] < max(pxy[j], pxy[j + 1]) && xxyy[k] > min(pxy[j], pxy[j + 1]) &&
xxyy[k] < max(xyp[i], xyp[i + 1]) && xxyy[k] > min(xyp[i], xyp[i + 1])) {


то ошибку "Необработанное исключение по адресу 0x0FC5E906 (ucrtbased.dll) в ConsoleApplication3.exe:
Недопустимый параметр был передан функции, для которой недопустимые параметры вызывают
неустранимую ошибку., произошло" выдаёт почему-то в 246 строке 

lxy.push_back(lxy[0]);


До этого тут ошибки не было, просто не все значения были правильно и всё.
http://cpp.sh/65v7n

UPD3: Исправила ошибку, чтобы после последней элемента строки не сдвигалось
было

move(pxy, { 1,0 });


стало  

        if(a<4){
            move(pxy, {1,0});
        }else
        {
            move(pxy, { -4,1 });
            cout << endl;
        }


Теперь выводит правильно, но только 3 строки из 4, на 4 он останавливается (опять
тут lxy.push_back(lxy[0]);). Есть предположение, что выдаёт ошибку, потому что ни одна
вершина первой клетки 4 строки не лежит в многоугольнике.
http://cpp.sh/6jpul

UPD4:
ошибка вот в чём, когда у нас ни одна точка клетки не принадлежит многоугольнику,
то массив lxy будет пустой, это значит, что я не могу записать первый элемент в конец
lxy.push_back(lxy[0]), поэтому мы должны проверить, не пустой ли массив.

if(lxy.size()>0){


Программа почти завершена.
    


Ответы

Ответ 1



Вот вам алгоритм подсчёта площадей. Перебираете все клетки, которые потенциально могут попасть в многоугольник. Для этого можно, например, описать вокруг него прямоугольник, взяв максимум/минимум абсциссы/ординаты вершин многоугольника, и все клетки в этом прямоугольнике и перебирать (кстати, такой прямоугольник называется "описывающий прямоугольник" или "bounding box"). Теперь анализируем каждую клетку. Анализ довольно прост. Если все 4 вершины клетки лежат в многоульнике - ответ 1. Если 3 вершины внутри, то из площади клетки (1) нужно вычесть площадь треугольника, который отрезается многоугольником. Для этого перебором всех рёбер многоугольника находим их пересечения с границами клетки, находим 2 точки пересечения, и после этого найти площадь отрезаемого треугольника не составит труда. Если только 2 вершины внутри, то действуем аналогично пункту 2, также находим 2 точки пересечения рёбер многоугольника с границами клетки, и отрезаем трапецию (или считаем площадь оставшейся трапеции). Если только 1 вершина внутри, то пересечения клетки с многоугольником является треугольником, аналогично пункту (1) ищется его площадь, которая и даст ответ.

Успешность выполнения миссий Бонда

#алгоритм


Нашёл одну интересную задачу. Буду думать над решением и неплохо бы услышать ваши
предложения:


  Каждый месяц Джеймс Бонд получает список миссий. Основываясь на своем богатом опыте,
он вычисляет вероятность успешного выполнения миссий каждой из своих кузин Джими Бонд
номер X. 
  
  Ваша программма должна обработать эти данные и найти такое разделение миссий между
кузинами, чтобы получить наибольшую вероятность того, что все миссии будут успешно
выполнены.
  
  Замечение: вероятность того, что все миссии будут успешно выполнены, равна произведению
вероятностей того, что отдельные миссии будут выполнены успешно. 
  
  Формат ввода
  
  Первая строка содержит целое число N - количество миссий (1 <= N <= 20). Следующие
N строк содержат по N целых чисел от 0 до 100, включительно. j-тое целое число на i-той
строке означает вероятность того, что кузина i выполнит успешно миссию j. Вероятность
задана в процентах.  
  
  Формат вывода
  
  Выведите максимальную вероятность успешного выполнения всех миссий, в процентах.
  
  Вывод отличающийся от официального ответа не более чем на +0.000001, будет принят.
  
  Примеры

input        input       input    
2            2           3        
100 100      0 50        25 60 100
50 50        50 0        13 0 50  
                           12 70 90 

output       output      output
50.000000    25.00000    9.10000

  
  Пояснение к 3-му примеру:
  
  Если Джимми 1 назначить 3-ю миссию, Джимми 2 назначить 1-ую миссию, а Джимми 3
назначить 2-ую миссию, то получим вероятность успеха равную 1.0 * 0.13 * 0.7 = 0.091
= 9.1%. Все другие варианты распределения миссий дают меньшую вероятность успеха.


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


Ответы

Ответ 1



Вроде придумал. Сегодня вечером протестирую и сообщю результаты. Решение: ДП по битовым маскам. Будем хранить в массиве f ответы меньшей размерности на нашу задачу. Индексы f - распределения миссий для кузин. Рассмотрим f[i]. Посмотрим на двоичное представление числа i. Например i = 100110. |**№ бита** | 5 | 4 | 3 | 2 | 1 | 0 | |------------+---+---+---+---+---+---| |**знач. i** | 1 | 0 | 0 | 1 | 1 | 0 | Это значит что в f[i] находится ответ, и если дали задание кузине с номером k, то k-ый бит равен 1. Причём, если количество ненулевых битов в числе i равно 3, то мы распределили кузин для первых 3 миссий. Конкретней реализация: Перебираем все маски (от 0 до 2^20 - 1 ~ 10^6), представляющие наше распределение (1). Для каждой маски считаем количество единиц в ней - это количество распределённых миссий м(2). Смотрим: какие кузины у нас не выполняют никаких заданий (3). Пробуем назначить какой-нибудь кузине задание v+1. (4) всё a[i, j] - вероятность выполнения миссии j кузиной i for msk := 0 to pow[n] - 1 do begin //pow[w] = 2^w; (1) v := q(msk); //(2) for i := 1 to n do // перебираем всех кузин if msk and pow[i-1] = 0 then //(3) f[msk or pow[i-1]] := max(f[msk or pow[i-1]],f[msk]*a[v+1,i]);// (4) end; ответ получим, когда распределили всех кузин, т. е. все биты = 1 (f[2^n-1]). Таким образом решение работает за N*2^N ~ 20.000.000 (< 1 секунды будет выполнятся алгоритм). Полный код: const maxN = 21; maxS = 1 shl maxN; var n,m,i,j,msk,v : longint; a : array [1..maxN,1..maxN] of double; f : array [1..maxS] of double; pow : array [0..maxN] of longint; function q(w : longint) : longint; var res : longint; begin res := 0; while w > 0 do begin if w and 1 = 1 then inc(res); w := w shr 1; end; q := res; end; function max(w1,w2 : double) : double; begin if w1 > w2 then max := w1 else max := w2; end; begin readln(n); for i := 1 to n do for j := 1 to n do begin read(a[i,j]); a[i,j] := a[i,j] / 100; end; pow[0] := 1; for i := 1 to maxN do pow[i] := pow[i-1] shl 1; for i := 1 to n do f[pow[i-1]] := a[1,i]; for msk := 0 to pow[n] - 1 do begin v := q(msk); for i := 1 to n do if msk and pow[i-1] = 0 then f[msk or pow[i-1]] := max(f[msk or pow[i-1]],f[msk]*a[v+1,i]); end; writeln(f[pow[n]-1]*100:0:10); end.

Ответ 2



У меня нет возможности комментировать(мало репутации), поэтому даю ответом. Какие ограничения на скорость алгоритма? Можно попробовать перебором. Если число кузин(X) == числу миссий, то всего вариантов X!. Можно перебирать все числа от 1 до X^X, переводить их в X-ичную систему счисления(например функцией itoa(number, outString, X)), затем разбить число на цифры(Цифра будет скажем номером кузины которая делает миссию с номером равным порядковому номеру цифры в числе), если какие-то 2 цифры одинаковые, то сразу переходим к следующей итерации цикла, иначе считаем общую вероятность и записываем в глобальную переменную max. Да, решение некрасиво и неэффективно, но это первое что пришло в голову. При большом количестве кузин будет очень долго считать, но зато надёжно.

Развертывание приложений Java на сервере

#java #веб_программирование


Нужен совет новичку на Java. Во всяких технологиях, IDE... уже как-то разбираемся
(в основном для desktop приложений), но про развертывание приложений на web-сервере
еще много вопросов.  

Основные особенности разрабатываемого приложения:   


Должны быть две версии - web и кроссплатформенная desktop.
Удобство установки, использования, обновления настольной версии для пользователя.
Версия web должна выполняться на стороне сервера, что бы снять нагрузку с клиента,
например актуально для iPad.  
Небольшая БД, авторизация пользователей.  
Хотелось бы не писать один и тот же код по два раза каждый раз в ходе разработки
и поддержки (для desktop и web отдельно).  
Приложение не очень сложное, предполагается развитие в сторону осуществления социальной
сети между зарегистрированными пользователями, только для web-версии.


Теперь вопросы:


От чего отталкиваться, от desktop или web, т.е. выкладывать настольную версию на
сервер или можно наоборот - заставить web-версию запускаться в Windows, Linux, Mac OS?  
Можно ли desktop-приложение Java разместить на web, что бы оно выполнялось на стороне
сервера?  
Если web-приложение работает локально, надо запускать соответствующие сервера, что
уже неудобно для обычного пользователя, нельзя ли обойтись по другому?

    


Ответы

Ответ 1



Не надо ни от чего отталкиваться. Разрабатывайте общие части в виде отдельных модулей-библиотек. Так получится переиспользование кода. Можно, но ни в коем случае не нужно. А зачем обычному пользователю запускать у себя сервера? UPD: хороший вариант, т.е. создаем два проекта и используем общие модули? еще не понимаю как интерфейс разрабатывать, отдельно придется писать? Ну да, делаете общую модель данных и общую бизнес логику в shared модулях и два отдельных приложения, которые эти модули используют. не нужно с учетом условия выполнения приложения на сервере? А какой смысл запускать десктопное приложение на сервере? Как вы себе это представляете? Как пользователь окно увидит? не совсем еще понимаю, а как локально можно запустить web-приложение? Традиционно веб-приложения выполняются на сервере и отображаются в веб-браузере пользователя + JavaScript выполняется на стороне клиента. UPD2 Чтобы показать друзьям, веб-приложение надо развернуть на сервере или на своей машине и открыть к нему доступ из интернета путём настройки своей машины и роутерамодемаetc. Если надо показать без доступа к интернету, то придётся все необходимые сервера устанавливать у них, либо использовать какие-то portable-версии этих серверов, которые работают без установки. Можно в одну директорию затолкать все нужные сервера (тот же tomcat не требует установки) и сервер БД, если требуется. И напишите скрипт, чтобы всё это запускать одним движением руки.

Ответ 2



Хотелось бы не писать один и тот же код по два раза каждый раз в ходе разработки и поддержки (для desktop и web отдельно). Прочитайте про шаблон MVC, это поможет вам разобраться, каким образом избежать дубликации кода, когда необходимо иметь несколько различных представлений для одного и того же функционала (веб-приложение, десктопные приложения на различные ОС, мобильные платформы и т.д.) Если вкратце, вам необходимо разделить на отдельные независимые модули безнес-логику и визуальное отображение. Можно ли desktop-приложение Java разместить на web, что бы оно выполнялось на стороне сервера? Сервер — это просто компьютер, который умеет отвечать на HTTP-запросы HTTP-ответами. Он сможет выполнять те же функции, что и ваш домашний компьютер. Вам будет нужно принять HTTP-запрос, при его обработке вызвать функции, которые вы называете "desktop-приложение Java" и затем вывести результат работы пользователю через HTTP-ответ. Таким образом вы выполните код на стороне сервера.

Рисование в андроид

#android #canvas


Необходимо реализовать рисование по экрану. Аналогично кисти в виндовском поинте.
Т.е мы зажали палец на экране и водим, за ним рисуется линия, отпустили - перестала.
Полный аналог рисования кисти в поинте. Есть идеи как такое реализовать?    


Ответы

Ответ 1



ApiDemos -> TouchPaint смотрите

Ответ 2



Вот тут описан пример создание простой рисовалки для Android

Ботнет для Android

#android #безопасность


Я изучаю Java + Android. И наткнулся на статью о ботнетах для Android. И мне стало
интересно, какие же в этой системе уязвимости. Казалось бы, в основе Android лежит
Linux. В описание написано, что это многопользовательская ОС, где каждое приложение
- это отдельный юзер, который имеет ID. Причем это ID неизвестно в приложении. Если
создать какой-нибудь файл (из приложения), то права доступа будут только для этого
ID. Я почти незнаком с системой Linux, и поэтому мне интересно, какие же уязвимости
там есть. И какими пользуются злоумышленники, создающие вредоносные программы для Android.
Я так предполагаю, они это пишут не на Java...    


Ответы

Ответ 1



Самая простая уязвимость -приложение рассылает платные смс или просто рассылает спам. Главное запросить привелегии и надеятся, что пользователь не заметит. Следующая уязвимость - собрать побольше персональных данных и отправить кому нужно на сохранение. В целом, если не использовать рутованые устройства и смотреть на то, какие привелегии запрашивает приложение, можно отсекать 99% вирусов и ботов.

Дата по-русски через setlocale

#php #локаль


setlocale(LC_TIME, "ru_RU.CP1251");
$date = strftime("%d %B, %H:%M",strtotime($row['date']));


Почему-то, если использовать код выше, то вроде все ок, дату выводит, но месяц по-прежнему
выводится по-английски: 26 May, 21:24. Если использовать:

setlocale(LC_TIME, "ru_RU");
$date = strftime("%d %B, %H:%M",strtotime($row['date']));


То дата выводится коряво: 26 јРЩ, 21:24

Как исправить? 
    


Ответы

Ответ 1



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

Почему LSB ELF shared object можно изменять “на лету”, а executable нет?

#executable #elf #linux


Сразу предупреждаю, вопрос праздный, чисто от любопытства.
Известно, что работающий executable (например a.out) поменять нельзя 

bash: a.out: Text file busy

а с загружаемой shared library (.so) это проходит без проблем. Естественно, изменения
для уже работающих программ будут видны только после dlclose(), dlopen().
Поискал часочек в сети, но ничего не обнаружил. Поскольку (в данный момент) практического
интереса вопрос для меня не имеет (просто интересно) лезть в исходники системы не хочу.
Кто-нибудь может объяснить такое различие в поведении системы (например, fopen("a.out","a+"))
по отношению к этим (в общем, очень похожим (или тут я не прав?)) объектам?
Update
Могу предположить, что .so (аналогично Solaris) отображаются на swap, хотя в Linux
Journal пишут:

...The filesystem cache, program code and shared libraries have a filesystem source,
so the RAM associated with any of them can be reused for another purpose at any time.
Should they be needed again, Linux can just read them back in from disk. ...

Как гуру думают, это объясняет наблюдаемое явление?
UPDATE-2
Про .so
Поскольку для .so делается mmap()  MAP_PRIVATE система по сути включает Copy-on-Write
для .so страниц и при модификации страницы в файле отобразит ее на swap для каждого
процесса, подключившего ее. Так что понятно откуда она подкачиваться будет (если потом
потребуется).
Почему text file busy возникает с a.out, а  с .so нет. 

В переписке долго обсуждается флаг MAP_DENYWRITE и почему его нельзя разрешать устанавливать
из user-mode. (а именно оттуда делается mmap() для .so). При запуске binary ядро этот
флаг устанавливает. 
Лично у меня сложилось впечатление, что достаточно было бы MAP_PRIVATE и для binary,
также как и для .so, но спорить о вопросах безопасности Линусу не хотелось. На самом
деле (практически) MAP_DENYWRITE для исполняемого a.out не мешает, но и не помогает
(IMHO). 
Важно, чтобы изменить код уже исполняющейся программы было трудно.
Пожалуй все, в данном вопросе я свое любопытство (спаcибо @northerner !) удовлетворил,
но пока тему не закрываю. Возможно кто-нибудь захочет обсудить подобные вопросы в своих
ответах.    


Ответы

Ответ 1



Ага, вот вроде бы оно: http://lkml.indiana.edu/hypermail/linux/kernel/0110.0/0476.html. Там довольно обширная дискуссия, сообщений сорок.

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

#запрос #mysql


Есть такой запрос
SELECT SUM(`total`) AS `sum`,CONCAT_WS('-',year(FROM_UNIXTIME(`unix`)),DATE_FORMAT(FROM_UNIXTIME(`unix`),'%m'))
AS `key` FROM `shop_orders` WHERE `status` NOT IN (1,6) AND `unix` BETWEEN ".(int)$start."
AND ".(int)$end." GROUP BY `key`

Возвращает он массив данных формата [2012-08] => 4252.00
В переменных $start и $end unix-даты начала августа 2011 и конца августа 2012 соответственно.
Если в БД нет записей с датой какого-нибудь месяца, то ключ с этой датой естественно
отсутствует, это логично.
Вопрос: возможно ли перестроить запрос таким образом, чтоб ключи были в любом случае,
а если данные отсутствуют, то значение было 0?
Пример (при отсутствии данных в БД за апрель и июнь):
[2012-04] => 0
[2012-05] => 152.00
[2012-06] => 0
[2012-07] => 5721.00
[2012-08] => 4252.00
    


Ответы

Ответ 1



Воспользуйтесь ф-цией IFNULL()

Оптимизация петель методом Даффа, кто-нибудь применял его на практике?

#c #оптимизация


Оригинальный copypaste. Функция копирования по указателю.
register short *to, *from;
    register count;
    {
        register n=(count+7)/8;
        switch(count%8){
        case 0: do{ *to = *from++;
        case 7:     *to = *from++;
        case 6:     *to = *from++;
        case 5:     *to = *from++;
        case 4:     *to = *from++;
        case 3:     *to = *from++;
        case 2:     *to = *from++;
        case 1:     *to = *from++;
            }while(--n>0);
        }
    }

Выгода очевидна. Петля распараллеливается, следовательно уменьшается количество сравнений
с условием цикла и благодаря switch без break первый проход можно начать из любой точки,
что позволяет без проблем копировать количество байт не кратное количеству строк внутри
петли, при этом оставив ее параллельной.
Кто-нибудь замерял насколько код выше работает быстрее обычной петли снизу?
do {                        
    *to = *from++;        
} while(--count > 0);
    


Ответы

Ответ 1



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

Очередь задач в PHP

#очередь #php #yii


По мере создания своего проекта столкнулся с проблемой - есть некоторые действия
пользователей, которые могут длиться до нескольких минут. Ясно понятно, что заставлять
пользователя ждать, пока выполняются такие длинные запросы к серверу непозволительно!
И тут пришел к выводу, что нужно организовать очередь задач, чтобы пользователь нажал
ссылку, на сервере сформировалась задача, а пользователю лишь только отображался процесс
выполнения задачи.

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

Слышал о RabbitMQ, Apache Message Queue, но мне кажется, что они слишком избыточны
для моего случая. Мне нужно-то, делать некоторые проверки на сервере (тут как раз пригодился
бы способ выполнения PHP кода, и в зависимости от результата продолжалось бы выполнение
задач, или нет), и манипулировать учетными файлами, и просто "тяжелыми" файлами.

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

Проект создается на базе фреймворка Yii.
    


Ответы

Ответ 1



Воркер на пхп и запускать его по крону. Не?

Ответ 2



ПО мере создания своего проекта столкнулся с проблемой такого плана - есть некоторые действия пользователей, которые могут длиться до нескольких минут. Это ужасно! Это следствие плохой структуры БД и скриптов. Что такого может выполняться, да к тому же у каждого пользователя по минуте по две? Ладно обработка нескольких таблиц с математическими действиями по подсчете скидок у 16К клиентов и 25К заказов. Тут да у меня на серваке до 8 минут считаются, но раз в день и для всех сразу, а не для каждого по отдельности. Я даже набросал табличку в БД, и все бы хорошо, но решение получилось не универсальным. Созданная очередь задач умеет выполнять только шелл скрипты, а мне бы хотелось научить ее выполнять еще логику на php, и чтобы результаты обоих случаев складывались в БД. В Yii есть консольные приложения(и тут), юзай их. Делай там и логику и операции с данными. Не нужно изобретать с данном случае велосипед.

Выбор key-value storage

#cpp #nosql


Необходимо обеспечить доступ к набору данных вида (key, value) где key - числовой
идентификатор, а value - динамический массив. На С++ я описал бы структуру так:
typedef struct {
    int id;
    int time;
    double value;
} item;

typedef std::unordered_map > my_storage;

Но, к сожалению датасет не помещается в оперативную память. Поэтому нужно выбрать
какое-то хранилище данных. Задача имеет следующие особенности:

Длина динамических массивов распределена экспоненциально (половина массивов вообще
состоят из одного элемента).
Хранилище заполняется постепенно: данные вида std::pair поступают
отсортированные по полю item.time и добавляются в конец соответствующего динамического
массива.
Хранилище должно обеспечивать операции двух видов: чтение целого массива по ключу
и добавление одного элемента в конец соответствующего ему массива
Вероятность обращения к конкретному массиву зависит от поля item.time последнего
элемента массива (тоже экспоненциально). Так как каждый массив отсортирован по возрастанию
item.time, можно сказать, что вероятность обращения зависит от времени последнего обращения
к нему.

Я нагуглил несколько вариантов таких хранилищ: LevelDB, Berkeley DB, Kyoto Cabinet...
Даже бенчмарк нашел: 
Требования к базе такие:

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

Данных будет где-то 50-200 Gb (это если слепить в один массив все структуры типа item).
Ну, собственно, прошу помочь тех, кто  работал с перечисленными выше БД. Или, может,
что-нибудь другое предложите?
UPD:
Забыл добавить, что задание скорее учебное, поэтому ни транзакции, ни конкурентный
доступ с большого числа клиентов, ни постоянная синхронизация не нужны.
Нашел еще решение: HDF5. Позиционируется как раз, как хранилище для научных данных.
Кто работал с ним, можете прокомментировать?
Еще хотел спросить у знающих людей, какие FS + mount options использовать, чтобы
избежать ненужного журналирования?    


Ответы

Ответ 1



Я бы использовал LevelDB, но со сложным ключом (основной идентификатор + номер в массиве или time), чтобы значением был только один элемент, а не массив. Поскольку в LevelDB данные отсортированы по ключу, то можно пробежаться по следующим/предыдущим ключам и получить весь массив.

Ответ 2



То, что Вы превели, в качестве примера - не предназначенно для этого, как минимум, будет очень медленно. Для таких объемов, скорее что-то на https://ru.wikipedia.org/wiki/Hadoop с https://ru.wikipedia.org/wiki/Apache_Cassandra.

Перевод в двоичную систему счисления больших чисел

#математика #c #алгоритм #cpp


Доброго времени суток!
Возник вопрос: как очень большое десятичное число(количество десятичных знаков ~10^4)
быстро перевести в двоичную систему счисления?
P.S. так как ни один тип такое число не уместит, то число считывается в строку, ну
или на лету обрабатывать нужно
P.P.S сторонние либы использовать нельзя    


Ответы

Ответ 1



В общем, решил я так: Из второго тома Д.Кнута алгоритм(спасибо @VladD за то что указал где искать): для числа, имеющего M+1>1 разрядов: ENT1 M-1 j ← m-1 LDA INPUT+M U ← u_m 2H MUL =10= SLAX 5 ADD INPUT,1 U ← 10U + u_j DEC1 1 J1NN 2B Повторять при m > j ≥ 0 и мой код на C: #include #include #include using namespace std; int main() { //обрабатываем случай, когда у числа всего 1 десятичный разряд char first = getc(stdin), second = getc(stdin); ungetc(second,stdin); ungetc(first,stdin); if(second=='\n') ungetc('0',stdin); //выделяем память "с запасом" под худший случай - 10^10000 десятичных знаков ~=32кб bool* arr = (bool*)malloc(sizeof(bool)*34000); bool* arr1; int end = 0; for(int i=0;i<34000;i++,arr[i]=false); int a=(int)getc(stdin)-48; //записываем самый старший разряд числа "как в школе учили" делением на 2 do{ arr[end]=(bool)(a&1); a>>=1; end++; }while(a); a=(int)getc(stdin)-48; //обрабатываем остальные разряды while(a!=-38){ //реализуем умножение текущего накопленного значения на 10: //x*10 = x*8 + x*2 == x<<3 + x<<1 arr1 = (bool*)malloc(sizeof(bool)*(end+4)); arr1[0]=false; //записываем число сдвинутое на 1 memcpy(arr1+1,arr,end+3); //сдвигаем само число на 3 memmove(arr+3,arr,end); arr[0]=false;arr[1]=false;arr[2]=false; end+=3; //суммируем выше полученные числа bool nextOverhead,overhead=false; for(int i=1;i<=end;i++){ nextOverhead=((arr[i]&&arr1[i]) || (arr[i]&&overhead) || (arr1[i]&&overhead)); arr[i]^=arr1[i]^=overhead; overhead=nextOverhead; } if(arr[end])end++; //прибавляем следующий разряд overhead=false; for(int i=0;a || nextOverhead;i++){ nextOverhead=((arr[i] && ((bool)(a&1))) || (arr[i] && overhead) || (((bool)(a&1)) && overhead)); arr[i]^=overhead^=((bool)(a&1)); overhead=nextOverhead; a>>=1; } if(arr[end])end++; a=(int)getc(stdin)-48; free(arr1); } for(int i=end-1;i>=0;i--) printf("%d",arr[i]); return 0; }

Ответ 2



@miramentis, ловите. #include #include #include #include int getdecbits (char arr[]) { int end = -1, a; if (isdigit(a = getchar())) { end = 0; a -= '0'; do { arr[end++] = a & 1; } while ( a >>= 1 ); } return end; } // вычисление y = x * 10 + d как x >> 3 + x >> 1 + d // складывает x3[], x1[] и d[] // (двоичные, один бит в байте, старшие справа) // (в x3[] и x1[] д.б. досаточно старших нулевых бит) // Returns длину результата >= max(l1, l2, l3) int add3 (char res[], char x3[], int l1, char x1[], int l2, char d[], int l3) { int i, s = 0; for (i = 0; i < l3; i++) { s += x3[i] + x1[i] + d[i]; res[i] = s & 1; s >>= 1; } for (; i < l2; i++) { s += x3[i] + x1[i]; res[i] = s & 1; s >>= 1; } for (; i < l1 && s; i++) { s += x3[i]; res[i] = s & 1; s >>= 1; } if (s) do { res[i++] = s & 1; } while ( s >>= 1 ); else for (; i < l1; i++) res[i] = x3[i]; return i; } int correct_nbits (char a[], int l) { while (l > 0 && !a[l]) l--; return l + 1; } #define N (64 * 1024) int main () { char array1[N], array2[N], a[4], *res, *prev_res; int nbits, curbits = 1; memset(array1, 0, sizeof(array1)); memcpy(array2, array1, sizeof(array1)); res = array1 + 3; prev_res = array2 + 3; while ((nbits = getdecbits(a)) > 0) { curbits = add3(res, prev_res - 3, curbits + 3, prev_res - 1, curbits + 1, a, nbits); memcpy(prev_res, res, curbits); } printf("Result: (%d bits)\n", curbits = correct_nbits(res, curbits)); for (int i = curbits - 1; i >= 0; i--) // for (int i = 0; i < curbits; i++) putchar(res[i] + '0'); puts(""); return puts("End") == EOF; } avp@avp-ubu1:~/hashcode$ gcc -std=gnu99 bigdec-bin.c avp@avp-ubu1:~/hashcode$ ./a.out 15 Result: (4 bits) 1111 End avp@avp-ubu1:~/hashcode$ ./a.out 32 Result: (6 bits) 100000 End avp@avp-ubu1:~/hashcode$ avp@avp-ubu1:~/hashcode$ gcc -std=gnu99 bigdec-bin.c -O3 avp@avp-ubu1:~/hashcode$ ./mkdigs 30 367535629127093606261879202375 avp@avp-ubu1:~/hashcode$ ./mkdigs 3 | ./a.out Result: (9 bits) 101101111 End avp@avp-ubu1:~/hashcode$ time ./mkdigs 10000 | ./a.out >/dev/null real 0m0.288s user 0m0.284s sys 0m0.000s avp@avp-ubu1:~/hashcode$ В исходника размер массивов 64КБ, достаточно для преобразования avp@avp-ubu1:~/hashcode$ time ./mkdigs 19700 | ./a.out >/dev/null real 0m0.890s user 0m0.892s sys 0m0.000s avp@avp-ubu1:~/hashcode$ примерно 19700 десятичных цифр. А вот исходника ./mkdigs не сохранилось, но он тривиален, на основе rand() % 10.

Ответ 3



Ребята, которые 10 триллионов знаков пи вычислили как-то сделали за O(n*log(n)^2). Можно скачать их исходники и попытаться понять, как. Или спросить. http://www.numberworld.org/y-cruncher/#Algorithms Возможно, они делят с остатком исходное число на 10^N, где N - такое, чтобы количество цифр в целом и остатке было одинаковым. А далее - рекурсивно для полученных половинок. Upd: если вам не интересен алгоритм O(n*log(n)^2), пристойный алгоритм O(n^2) - static const int bitsInCell = 28; unsigned int data[32000 / bitsInCell + 10]; int i, dataLen = 1; char ch; memset(data, 0, sizeof(data)); for (i = 0; i < 8; i++) { ch = getc(stdin); if (!isdigit(ch)) break; data[0] = data[0] * 10 + ch - '0'; } if (isdigit(ch)) while (true) { ch = getc(stdin); if (!isdigit(ch)) break; // Умножаем на 10 data[0] = data[0] * 10 + ch - '0'; for (i = 0; i < dataLen; i++) { unsigned int carryValue = data[i] / (1U << bitsInCell); data[i] %= 1U << bitsInCell; data[i + 1] = data[i + 1] * 10 + carryValue; } if (data[dataLen] > 0) dataLen++; } // Вывод битов из data

Ответ 4



Перевести исходное число в систему счисления с основанием 109 (можно по Кнуту, можно через sscanf()). "Цифры" хранить в 32-битовом целом формате. Перевести "уголком" полученное число в систему счисления с основанием 232, при делении использовать расширенные умножения и сдвиги. Запись остатков-"цифр" в массив результата идёт в обратном порядке. Перевести каждую новую "цифру" в 32-символьную двоичную строку, начиная с последней (например, через sprintf()). В последней строке убрать ведущие нули, в остальных - сохранить.