• Как модернизировать ф-цию, чтобы она искала целы слова?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Может быть так?


    если же вам нужно четкое соответствие слов (то есть "остров" равен "остров" но не равен "острова") то решение будет таким:
    Ответ написан
    6 комментариев
  • Как вывести результат js скрипта?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Как то так наверное:


    PS: сумму аванса и зарплаты считать не стал, потому в этих колонках нули. Уверен с этим Вы вполне справитесь сами :)
    Ответ написан
  • Какую БД выбрать для Electron-приложения?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    для реляционной БД - SQLite
    для NOSQL БД - nedb (хабр. nedb полностью встраиваемая в приложение, почти в полном объеме реализует систему запросов как в mongodb)
    Ответ написан
    Комментировать
  • Определить самое длинное число в строке?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    2 комментария
  • Как найти общие подстроки в нескольких строках на JavaScript?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Есть более простое (алгоритмически) решение.
    Общая суть его такова, вместо построения матрицы N1 x N2 делаем последовательный сдвиг меньшей строки относительно большей (1 цикл длинной N1+N2-2). На каждой итерации этого сдвига делаем второй цикл через текущую область пересечения этих строк, подсчитывая совпадения символов и запоминая их, если число совпадений больше предыдущего. Так же время выполнения такого алгоритма будет не O(Nmax*Nmin) а O(Nmax*Nmin -Nmin)

    Если не поленюсь, оформлю с утра в виде кода)

    PS: Заставляете не полениться:) Для поддержки поиска по строкам в количестве больше 2-х алгоритм был несколько модифицирован. Для удобства понимания почти не использовал "особые фишки" JavaScript-а, все выполнено на обычных циклах.
    код с комментариями

    function search_largest_substr(){
    	/*
    	Наибольшая общая строка не может 
    	быть больше наименьшей входной строки.
    	Находим наименьшую и по ходу формируем
    	массив с остальными:
    	*/
    
    		// в эту переменную внесем самую маленькую подстроку
    		let str_min = arguments[0];
    		// сюда сложим все остальные подстроки
    		const list = [];
    		
    		// пробежим в цикле по всем переданным в функцию аргументам
    		for(let n=1; n<arguments.length; n++){
    			// если строка в str_min меньше чем в
    			if(str_min.length<arguments[n].length){
    				// вносим в list текущую строку
    				list.push(arguments[n]);
    				// переходим к следующей итерации цикла
    				continue;
    			}
    
    			// иначе в list строку, лежащую в str_min
    			list.push(str_min);
    			// запоминаем в str_min текущую строку
    			str_min = arguments[n];
    		}
    
    	/*
    	Далее нам надо проверить наличие всех возможных
    	подстрок из самой маленькой строки в других строках.
    	Например если самая маленькая подствока была "abcd"
    	то надо последовательно проверить 
    	"abcd", "abc", "bcd", "ab", "bc", "cd", "a", "b", "c", "d"
    	Но при этом, как только будет найдена подстрока имеющаяся
    	во всех строках надо сразу завершить цикл с проверкой.
    	*/
    		// Данный цикл будет определять текущий размер 
    		// проверяемой подстроки, начиная от наибольшего возможного.
    		// Например для строки "abcd" это будут значения 4, 3, 2, 1
    		for(let l=str_min.length; l>0; l--){
    
    			// В данном цикле определяем позицию подстроки.
    			// Например для строки "abcd" это будут значения:
    			// при l=4 будут 0
    			// при l=3 будут 0, 1
    			// при l=2 будут 0, 1, 2
    			// при l=1 будут 0, 1, 2, 3
    			for(let p=0; p<=str_min.length-l; p++){
    				// берем из наименьшей строки тестируемую подстроку
    				const substr = str_min.slice(p, p+l);
    
    				// если искомый фрагмент есть во всех строках
    				// то isFound будет присвоено true
    				let isFound = true;
    
    				// далее в цикле проверяем все остальные строки 
    				// на наличие искомой подстроки
    				for(let i=0; i<list.length; i++){
    					// если искомая подстрока присутствует в
    					// текущей строке - ничего не делаем
    					if(	list[i].indexOf(substr) >= 0)
    						continue;
    
    					// иначе выставляем isFound=false 
    					// и прерываем текущий цикл по i
    					isFound=false;
    					break;
    				}
    
    				// если isFound == true значит нужная подстрока найдена
    				if( isFound )
    					return substr;
    
    				// иначе продолжаем поиск
    			}
    		}
    
    		// если не было найдено ни единой соврадающей подстроки
    		// возвращаем пустую строку
    		return "";
    }
    
    
    // Исползуем функцию поиска так:
    var str = search_largest_substr("ABCDEFGH", "ABCDEFG", "ABCDEF");
    console.log(str);
    
    
    str = search_largest_substr("123445", "12654", "123768");
    console.log(str);


    Ответ написан
  • Почему поиск работает только при определённом имени поля input?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Потому что при нажатии формируется url
    https://www.bing.com/?inputname=строкапоиска
    Где вместо "inputname" будет содержимое поля name у инпута а вместо "строкипоиска" будет введенный нами в инпут текст.

    При этом бинг при поиске требует чтобы строка поиска была передана как "q". Тоесть так:
    https://www.bing.com/?q=строкапоиска
    Ответ написан
    3 комментария
  • Возможно ли в браузере подсветить/выделить нужные слова в тексте страницы?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Лови :)



    PS: чуть поменял, цикл был не нужен)
    Ответ написан
    3 комментария
  • Как сделать временную ссылку?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Да, вполне.

    Для этого необходимо:
    1. Создать табличку в бд (или файлик) для хранения временных ссылок: соответствия абракадабры и имени файла на диске или ссылки на файл в Интернете, срока жизни ссылки, прав доступа и т.п.
    2. Создать роутер в экспрессе, например такой:

    ...
    app.use('/temp/:id', function(req, res, next){
      // console.log('ID:', req.params.id);
    
      // тут абракадабра лежит в req.params.id
      // далее вы достаете из БД данные о
      // полученом ID проверяете срок жизни
      // права доступа и отдаете локальный файл 
      // res.sendFile('/путь/до/файла/имяфайла');
    
      // либо делаете редирект на удаленный файл
      // res.redirect('remote.server/test.img');
    
      // или сообщаем о причинах отказа
      // доступа к этому файлу
      // res.send('Вы не правы:)');
    }
    ...


    ПРОФИТ.
    Ответ написан
  • Как правильно протестировать Express приложение? Запуск http сервера - это норма или нет?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Не вижу ни каких проблем связанных с использованием http серева при тестах. Более того, экспресс сам по себе является таким сервером, и все его роутеры завязаны на него, получая в реквесте кучу информации, включая http заголовки и много чего еще. Теоретически наверно можно создать систему тестирования, работающую без запуска реального сервера, но для этого по крайней мере прийдется написать свой велосипед, который будет делать вид что он http сервер и подсунуть его в экспесс вместо реального. Более того, такой велосипед должен будет в полном объеме эмулировать api модуля http. Возможно такой велик даже существует, но все это кажется мне гораздо более ненадежным и неимеющим смысла. Хотя решать конечно Вам.
    Ответ написан
    4 комментария
  • Как получить id элемента используя addEventListener и getElementsByClassName?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    // получаем массив элементов с именем класса 'slider-nav__dot'
    var dots = document.getElementsByClassName('slider-nav__dot');
    
    // перебираем в цикле все элементы из массива
    for (var i = 0; i < dots.length; i++) {
      // ВНИМАНИЕ!!!!
      // создаем анонимную, само вызывающуюся функцию 
      // в качестве параметра ей передается i
      (function (index) {
        // ВНИМАНИЕ!!!!
        // внутри этой функции переданный ей i уже index. 
        // И если i на всех итерациях это одна и та же переменная с разными значениями
        // то переменная index является самостоятельной переменной, 
        // со своим уникальным значением в каждой итерации цикла 
    
        // создаем функцию-слушатель события "click"  она существует (ее время жизни) 
        // до тех пор пока не будет удалена из слушателей.
        // Внутри нее используется переменная  index объявленная вовне
        // создавая тем самым ЗАМЫКАНИЕ. То есть для каждой итерации цикла
        // переменная index не будет удалена после завершения итерации
        // а будет продолжать жить как замыкание пока жива функция-слушатель ее использующая
        dots[index].addEventListener("click", function () {
          console.log(index);
        })
      })(i);
    
    
    }
    Ответ написан
    Комментировать
  • Ввести N целых чисел в 1-мерный массив. Вычислить количество элементов массива=0 и сумму их индексов. Как реализовать динамический массив?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    18 лет не программил на С и C++, поэтому могут быть ошибки)

    #include <iostream>
    #include <cstdlib>
    void main(void){
        // переменная для общего колличество значений
        int n;
    
        // переменная для колличества значений==0
        int zero = 0;
        // переменная для суммы индексов со значениями==0
        int zeroindex = 0;
    
        // ввод пользователем колличества значений
        std::cout << "введите колличество значений:";
        std::cin >> n;
    
        // Выделение памяти, достаточной для массива из n int
        int* arr = (int*)std::malloc(n*sizeof(int));
    
        // ввод пользователем n значений
        for (int i = 0; i < n; i++ ){
            std::cout << "введите значение №" << i << ":";
            std::cin >> arr[i];
            // если введен 0 то увеличиваем счетчик zero
            if( arr[i] == 0){
                zero++;
                zeroindex+=i;
            }
        }
    
        // выводим результаты расчетов
        std::cout << "колличество значений равных нулю:" << zero;
        std::cout << "сумма их индексов:" << zeroindex;
    
        // освобождаем выделеную память перед выходом
        std::free(arr);
    }
    Ответ написан
    3 комментария
  • Node js какую команду запустить чтобы увидеть приложение?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Было бы не плохо если бы вы дали ссылку на репозиторий. А так могу только перевести:)

    Clone the repository
    Сделайте клон репозитория (если реп на гите то команда git clone repoURL

    Open console in the cloned folder
    Откройте в консоли папку с клонированным репозиторием

    Run "npm install"
    Введите команду "npm install"

    Run "node ." to see the application CLI options
    Введите команду "node ." для просмотра опций консольного интерфейса приложения

    PS. Видимо вывод последней команды расскажет как запустить приложение и какие у него есть ключи
    Ответ написан
  • Полёт пули в игре html5+js?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    ArtC, выкладываю демонстрацию. Покликайте левой кнопкой мышки по листу с сеткой.

    код реализации цикла расчета и отображения пуль
    (function(exports) {
    	console.log("Billets");
    	"use strict";
    
    	/**
    	 * в данном модуле для векторных расчетов используется модуль Vector
    	 * его код доступен по ссылке https://game.lastuniverse.ru/gun.2d.01/js/vector.js
    	 * в этом модуле его функционал доступен через глобальную переменную window.libs.Vector
    	 */
    	// создаем сокращенную ссылку на функционал модуля vector.js
    	const Vector = window.libs.Vector;
    
    
    	/**
    	 * в данном модуле для отрисовки на canvas-е сетки, а также для масштабирования
    	 * используется специальная прослойка. В вашем случае вы будете просто сами рисовать через
    	 * 2d контекст canvas-а полученный с помощью ctx = canvas.getContext("2d");
    	 * здесь же я использую специальные врапперы, таким образом чтобы код 
    	 * представленный далее можно было использовать на обычном контексте canvas-а
    	 */
    	// создаем врапер на контекст канваса canvas.getContext("2d")
    	let ctx = window.libs.ctx;
    	// в вашем случае будет както так
    	// ctx = canvas.getContext("2d");
    
    
    	/**
    	 * Функция перерисовки сетки. В вашем случае это будет функция рисующая 
    	 * через ctx какой то фон на канвасе
    	 */
    	function redraw() {
    		window.libs.sheet.planedReDraw();
    		window.libs.sheet.reDraw();	
    		// в вашем случае будет както так:
    		// ctx.fillStyle="#1b1b1b"; // устанавливаем цвет фона
    		// ctx.fillRect(0,0,canvas.width,canvas.height); // зарисовываем канвас этим цветом
    
    	}
    
    
    	/**
    	 * для того чтобы интерфейс мог иметь доступ к параметрам пули и менять их
    	 * экспортируем объект с настройками и функциями данного модуля. 
    	 * В других модулях будет доступен как window.libs.bullets
    	 * в вашем случае в этом нет необходимости
    	 */
    	exports.bullets = {};
    
    	
    	/**
    	 * Настройки симуляции
    	 * settings.speed 		- скорость новых пуль
    	 * settings.size 		- размер новых пуль
    	 * settings.distance	- радиус жизни пуль
    	 */
    	const settings = {
    		speed: 10,
    		size: 10,
    		distance: 200
    	};
    	// экспортируем для интерфейса объект с настройками пуль. 
    	// В вашем случае в этом нет необходимости
    	exports.bullets.settings = settings;
    	
    
    
    
    
    
    	/**
    	 * Приготовления завершены, начинаем создавать пули !!!!
    	 */
    
    
    
    
    
    	
    	/**
    	 * массив с пулями. каждая пуля описывается объектом, содержащим ключи:
    	 * @key {object} loc 		объект {x: ..., y: ...} содержащий текущие координаты пули
    	 * @key {object} emitter 	объект {x: ..., y: ...} содержащий координаты из которых стартовала пуля
    	 * @key {object} direction 	нормализованный вектор/объект {x: ..., y: ...} содержащий направление полета пули (нормализованный - значит его длинна равна 1)
    	 * @key {number} distance	радиус жизни пули
    	 * @key {number} speed 		скорость пули
    	 * @key {number} size 		размер пули
    	 */
    	let bullets = [];
    
    	
    	/**
    	 * Обработчик собития click по рабочему пространству листа (canvas-а)
    	 * @param  {object} event 	имитация стандартного эвента события click (в вашем случае при использовании этого кода будет не имитация)
    	 */
    	function mouseclick(event){
    		add_bullet(
    			{ x: 0, y: 0 }, // летит из центра
    			{ x: event.clientX, y: event.clientY }, // по направлению к курсору мышки
    			settings.distance, // c радиусом жизни пули указанным в настройках
    			settings.speed, // со скоростью указанной в настройках
    			settings.size // с размером указанным в настройках
    		);
    	}
    	// экспортируем обработчик события click по листу. Будет вызван при клике на листе
    	exports.bullets.mouseclick = mouseclick;
    	// в вашем случае вместо этого вы сделаете так:
    	// canvas.addEventListener("click", mouseclick);
    
    
    	/**
    	 * функция добавления новой пули
    	 * @param {object} emitter 		объект {x: ..., y: ...} содержащий координаты из которых стартует пуля
    	 * @param {object} direction 	        не нормализованный вектор/объект {x: ..., y: ...} содержащий направление полета пули
    	 * @param {number} distance		радиус жизни пули
    	 * @param {number} speed     	скорость пули
    	 * @param {number} size 		размер пули
    	 */
    	function add_bullet(emitter, direction, distance, speed, size) {
    		
    		// заносим в массив с пулями новую пулю
    		bullets.push({
    			emitter: emitter,
    			loc: emitter,
    			direction: new Vector(direction.x, direction.y).normalize(),
    			distance: distance,
    			speed: speed,
    			size: size
    		});
    	}
    
    	/**
    	 * функция расчета следующей позиции пули
    	 * @param  {object} bullet 	объект, содержащий параметры пули: loc, emitter, direction, speed, size
    	 */
    	function calc_bullet(bullet) {
    		
    		// преобразуем координаты в объект класса Vector
    		const loc = new Vector(bullet.loc.x, bullet.loc.y);
    		
    		// рассчитываем вектор приращения в направлении движения пули для ее скорости
    		const vector = bullet.direction.multiply(bullet.speed);
    
    		// добавляем к координатам пули значение вектора с приращениями
    		bullet.loc = loc.add(vector).toLocate();
    	}
    
    	/**
    	 * функция расчета следующей позиции всех пуль.
    	 * также функция следит за удалением пуль при их
    	 * отлете на расстояние превышающее радиус жизни пули
    	 */
    	function calc_all_bullets() {
    		
    		// прокручиваем в цикле все пули
    		bullets.forEach(bullet=>{
    			
    			// расчитываем новые координаты очередной пули
    			calc_bullet(bullet);
    
    			// рассчитываем расстояние пули от точки старта
    			const distance = Math.sqrt( Math.pow(bullet.emitter.x-bullet.loc.x, 2) + Math.pow(bullet.emitter.y-bullet.loc.y, 2) );
    
    			// если дистанция болше чем дистанция жизни этой пули, запоминаем что ее надо удалить
    			if( distance > bullet.distance ){
    				bullet.toDelete = true;
    			}
    		});
    
    		// удаляем помеченые для удаления пули
    		bullets = bullets.filter(bullet=> !bullet.toDelete);
    	}
    
    	/**
    	 * функция отрисовки пули
    	 */
    	function draw_bullet(bullet) {
    		ctx.beginPath();
    		ctx.strokeStyle = "#fff";
    		ctx.fillStyle = "#f00";
    		ctx.arc( bullet.loc.x, bullet.loc.y, bullet.size, 0, Math.PI*2, false );
    		ctx.closePath();
    		ctx.fill();
    		ctx.stroke();		
    	}
    
    	/**
    	 * функция отрисовки всех имеющихся пуль
    	 */
    	function draw_all_bullets() {
    		
    		// прокручиваем в цикле все пули
    		bullets.forEach(bullet=>{
    			
    			// отрисовываем очередную пулю
    			draw_bullet(bullet)
    
    		});
    	}
    
    
    	/**
    	 * функция содержащая действия цикла игровой симуляции
    	 */
    	function play(){
    
    		// следующую строку в вашем случае нужно удалить
    		if(!ctx) ctx = window.libs.ctx;
    
    		// расчитываем новые координаты всех пуль
    		calc_all_bullets();
    
    		// перерисовыаем фон на листе (на канвасе)
    		redraw();
    
    		// перерисовыаем все пули
    		draw_all_bullets();
    
    		// панируем запуск следующей итерации игрового цикла через 20 милисекунд
    		setTimeout(play,20);
    	}
    
    
    	/**
    	 * запускаем функцию игрового цикла.
    	 */
    	play();
    
    })(this.libs=this.libs||{});



    PS: Так же Вы можете дополнительно посмотреть как реализованы векторные вычисления на плоскости canvas-a (вычисление расстояний, скоростей, направлений а также масштабирования) в этом ответе
    Ответ написан
    2 комментария
  • Как правильно написать такой простой скрипт?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    const list = ["Lacquered", "Acrylic", "Veneer", "Laminate", "Thermofused"];
    const row = 13;
    const rowStr = ".from-row:eq(" + row + ")";
    $(rowStr + " .select-change-item option.Lacquered").show();
        $(rowStr + " .select-change-item option:not(.Lacquered)").hide();
        $(rowStr + " .select-change").change(function() {
            list.forEach(item=>{
                if ($(rowStr + " .select-change").val() == item) {
                    $(rowStr + " .select-change-item option."+item).show();
                    $(rowStr + " .select-change-item option:not(."+item+")").hide();
                }
            });
        });
    Ответ написан
    5 комментариев
  • Как добавить на страницу js файл чтобы работал корректно?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    я у себя для подобных целей использую самописный велосипед:

    код модуля (тут можно посмотреть как реализована загрузка других модулей)
    (function(exports) {
    	console.log("Require", exports);
    
    	"use strict";
    
    	// создаем адресное пространство модуля
    	exports.require = load.bind(this);
    
    	/* функция загружает набор произвольных скриптов
    		 options может содержать:
    		 baseurl - адресс сервера на котором находятся скрипты
    							 вида "http://server/"
    							 если не задано берется из window.location
    		 path		- путь к папке со скриптами
    							 вида "your/path/to/scriptd/"
    							 если не задано берется ""
    		 modules - массив с названиями загружаемых скриптов
    							 вида ["script1","script2",...,"scriptN"]
    		 onready - callback функция, вызываемая по завершении загрузки
    							 всех модулей указанных в modules
    	*/
    	function load( options ) {
    		// выход если не указан ни один скрипт для загрузки
    		if( !options.modules )
    			return;
    
    		// если скрипт для загрузки указан в виде строки - переделываем в массив
    		if( typeof options.modules === 'string' )
    			options.modules = [options.modules];
    
    		// выход если скрипты для загрузки не массив
    		if( typeof options.modules != 'object' )
    			return;
    
    		// если не указан URL сервера - берем его из window.location
    		if( !options.baseurl || typeof options.baseurl != 'string')
    			options.baseurl = window.location;
    
    		// если не указан путь к скриптам - берем ""
    		if( !options.path || typeof options.path != 'string')
    			options.path = '';
    
    		// если не указана callback функция - создаем заглушку
    		if( !options.onready || typeof options.onready != 'function')
    			options.onready = function(){};
    
    		// создадим промис, который всегда выполнится
    		var sequence = Promise.resolve();
    
    		// Пройдемся по всем загружаемым модулям (скриптам)
    		for ( let name of options.modules ) {
    			const url =
    					options.baseurl
    				+ options.path
    				+ name;
    
    			// Добавляем действия с ними в конец последовательности
    			sequence = sequence.then( function() {
    				return loadScript( url );
    			} );
    			// .then(function(chapter) {
    			//	 addHtmlToPage(chapter.html);
    			// });
    		}
    
    		sequence.then( function() {
    			// все загрузились
    			options.onready();
    		} );
    
    	}
    
    	/* функция загружает произвольный скрипт по URL и выдает promise */
    	function loadScript( url ) {
    		let promise = new Promise( function( resolve, reject ) {
    			// Adding the script tag to the head as suggested before
    			let head = document.getElementsByTagName( 'head' )[ 0 ];
    			let script = document.createElement( 'script' );
    			script.type = 'text/javascript';
    			script.src = url;
    
    			// Then bind the event to the callback function.
    			// There are several events for cross browser compatibility.
    			script.onreadystatechange = cb;
    			script.onload = cb;
    
    			function cb() {
    				resolve();
    			}
    
    			// Fire the loading
    			head.appendChild( script );
    
    		} );
    		return promise;
    	}
    
    	// создаем ссылки на функции модуля в адресном пространстве модуля
    
    })(this.libs=this.libs||{});

    подключение модуля
    <!DOCTYPE html>
    <html>
    <head>
        <title>graph eginere</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script src="js/require.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
        ...
    </body>
    </html>

    как с помощью данного модуля загружать другие модули
    window.libs.require({
    		path: "js/",
    		modules: [
    			"polyfill.setimmediate.js",
    			"vector.js",
    			"events.js",
    		],
    		onready:()=>{
    			console.log("LOAD OK");
    		}
    	});

    пример модуля polyfill.setimmediate.js
    /**
     * Полифил для setImmediate 
     * (единственное что в неизмененном виде было взято гдето в Интернете)
     */
    if (!window.setImmediate) window.setImmediate = (function() {
    	var head = { }, tail = head; // очередь вызовов, 1-связный список
    
    	var ID = Math.random(); // уникальный идентификатор
    
    	function onmessage(e) {
    		if(e.data != ID) return; // не наше сообщение
    		head = head.next;
    		var func = head.func;
    		delete head.func;
    		func();
    	}
    
    	if(window.addEventListener) { // IE9+, другие браузеры
    		window.addEventListener('message', onmessage);
    	} else { // IE8
    		window.attachEvent( 'onmessage', onmessage );
    	}
    
    	return function(func) {
    		tail = tail.next = { func: func };
    		window.postMessage(ID, "*");
    	};
    }());

    пример модуля events.js
    (function(exports) {
    	console.log("Flow.Events");
    
    	"use strict";
    
    	/**
    	 * класс емиттера событий(почти eventemitter)
    	 * содержит функции on, once и emit
    	 */
    	exports.Events = Events;
    	function Events(){
    		// конструктор
    		//console.log("Events.constructor");
    		this.e = { };
    	};
    
    	/**
    	 * Установить слушатель для события @name
    	 * @param  {String}   name    стороковый идентификатор события
    	 * @param  {Function} cb      функция-слушатель. Вызывается при возникновении события @name
    	 * @param  {Number}   timeout функция-слушатель может быть вызвана 3-я разными способами 
    	 *                            1. незамедлительно при возникновении события (timeout не задан)
    	 *                            2. асинхронно, с незначительной отсрочкой (timeout равен 0)
    	 *                            3. асинхронно, через установленный интервал времени (timeout больше 0)
    	 * @param  {Boolean}  isOnce  если true, то слушатель будет вызван 1 раз, после чего будет удален
    	 * @return {Function}         функция, вызов которой удалит слушателя.
    	 */
    	Events.prototype.on = function(name, cb, timeout, isOnce) {
    		if (typeof cb !== 'function')
    			throw new Error('listener is not a function');
    		const e = this.e[name] = this.e[name]||[];
    		const d = this.mode(timeout);
    		if(isOnce) d.isOnce = true;
    		d.cb = cb;
    		e.push(d);
    		return function () {
    			const i = e.indexOf(d);
    			if(i!==-1) e.splice(i, 1);
    		}
    	};
    
    
    	/**
    	 * вычислить режим вызова обработчиков события
    	 * @param  {Number}   timeout функция-слушатель может быть вызвана 3-я разными способами 
    	 *                            1. незамедлительно при возникновении события (timeout не задан)
    	 *                            2. асинхронно, с незначительной отсрочкой (timeout равен 0)
    	 *                            3. асинхронно, через установленный интервал времени (timeout больше 0)
    	 * @return {Function}         Объект, может содержать поля поля timeout и isTimeout или isAsync или isSync
    	 */
    	Events.prototype.mode = function(timeout) {
    		const d = {};
    		if(typeof timeout === "number"){
    			if(timeout>0){
    				d.timeout = Math.ceil(timeout);	
    				d.isTimeout = true;
    			} 
    			else d.isAsync = true;
    		}
    		else d.isSync = true;
    		return d;
    	};
    
    	/**
    	 * установить глобальный режим вызова обработчиков события
    	 * @param  {Number}   timeout функция-слушатель может быть вызвана 3-я разными способами 
    	 *                            1. незамедлительно при возникновении события (timeout не задан)
    	 *                            2. асинхронно, с незначительной отсрочкой (timeout равен 0)
    	 *                            3. асинхронно, через установленный интервал времени (timeout больше 0)
    	 */
    	Events.prototype.setmode = function(timeout) {
    		 this.m = this.mode(timeout);
    	};
    
    	/**
    	 * отменить глобальный режим вызова обработчиков события
    	 */
    	Events.prototype.clearmode = function() {
    		 this.m = undefined;
    	};
    
    
    	/**
    	 * Установить одноразовый слушатель для события @name
    	 * @param  {String}   name    стороковый идентификатор события
    	 * @param  {Function} cb      функция-слушатель. Вызывается при возникновении события @name
    	 * @param  {Number}   timeout функция-слушатель может быть вызвана 3-я разными способами 
    	 *                            1. незамедлительно при возникновении события (timeout не задан)
    	 *                            2. асинхронно, с незначительной отсрочкой (timeout равен 0)
    	 *                            3. асинхронно, через установленный интервал времени (timeout больше 0)
    	 */
    	Events.prototype.once = function(name, cb, timeout) {
    		const off = this.on(name, function(){
    			off();
    			cb.apply(this,arguments);
    		}, timeout,true);
    	};
    
    	/**
    	 * Вызвать всех слушателей для события @name
    	 * @param  {String}   name    стороковый идентификатор события
    	 */
    	Events.prototype.emit = function(name) {
    		const e = this.e[name];
    		if(!e || !e.length) return;
    		const args = [].slice.call(arguments,1);
    		e.some( function(l) {
    			if(l.isEmitted) return;
    			if(l.isOnce) l.isEmitted = true;
    			const mode = this.m||l;
    			if(mode.isTimeout) {
    				setTimeout(function() { l.cb.apply(this, args); }, mode.timeout);
    			} else if(mode.isAsync) {
    				window.setImmediate(function() { l.cb.apply(this, args); });
    			} else {
    				l.cb.apply(this, args);
    			}
    			const event = args[0];
    			if(event.__stopImmediatePropagation) return true;
    			return false;
    		});
    	};
    })(this.libs=this.libs||{});

    Ответ написан
  • Как сделать из строки в строку, а затем массив?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Совершенно не понял суть этого вопроса:
    Надо сделать из final строку вида(1:17 где 1 цифра, а 17 сколько раз она повторилась),а потом массив;

    потому как final.innerHTML уже есть такая строка.

    Но взял на себя смелость слегка прилизать ваш "код"
    Ответ написан
  • Как сделать чтобы DOM элементы искало только по названию?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Вариант без регулярных выражений:

    Ответ написан
  • Как сделать точное вычисление физики гравитации на javascript в canvas методом Верле?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    elleremo, ускорение которое получают планеты пролетая вблизи других планет не является ошибкой!!!

    Этот эффект называется "гравитационный маневр для ускорения объекта" или же "гравитационная праща"

    Swingby_acc_anim.gifГравитационный манёвр для ускорения объекта (гравитационная праща)

    Не стал делать "точную имитацию" гравитации. Пошел по пути:
    1. каждый объект имеет массу равную объему объекта умноженному на плотность объекта
    2. каждый объект влияет на каждый динамический объект
    3. влияние пошагово рассчитывается по формуле (почти) :
    V = сумма(F); // суммарный вектор сил
    F = k*M/D; // сила влияния (расчитывается для каждого объекта оказывающего влияние на текущий)
    M - масса объекта
    D - квадрат расстояния между центрами масс объектов
    k - коэффициент для подгона скоростей (выполняет роль гравитационной постоянной)

    Алгоритм расчета (пошагово):
    1. Для каждого динамического объекта происходит расчет новых координат (сумма текущих координат и вектора скорости, рассчитанного на предыдущей итерации цикла симуляции)
    2. Каждый динамический объект сверяется с каждым объектом на предмет столкновения. Если расстояние между центрами 2х сравниваемых объектов меньше суммы их радиусов то происходит слияние. Если объединяются статичный и динамический объекты, то динамический удаляется а его масса добавляется к статическому с перерасчетом плотности, радиуса и объема. Если объединяются 2 динамических объекта то к первому добавляется масса второго с перерасчетом плотности, радиуса и объема, координаты и вектора скоростей пересчитываются как взвешеная сумма координат и векторов скоростей обоих объектов. После второй объект удаляется.
    3. Для каждого динамического объекта расчитывается сумма векторов силы влияния притяжения всех объектов. Затем данная сумма и вектор скорости текущего объекта суммируются
    4. Переход к новой итерации цикла симуляции.

    Вся реализация расчета тут (в конце скрипта). Все формулы вынесены в класс Calc.

    видеодемонстрация
    демонстрация (масштабируется колесиком мышки, перетаскивается с помощью ЛКМ)

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

    5bbd21b57da99316097769.png
    Добавил настройки:
    • параметры отображения
      • отображать сетку - вкл/выкл отображение координатной сетки
      • отображать источники - вкл/выкл отображение объектов, генерирующих планеты
      • отображать шлейф - вкл/выкл отображение траектории планет

    • Настройки физических величин - позволяют задаь минимальные и максимальные значения для размеров и плотности статических и динамических объектов
    • Управление симуляцией
      • шаг симуляции - экспериментальная величина регулирующая точность расчетов
      • скорость источников - изменяет скорость, с которой источники генерируют планеты
      • включить источники - вкл/выкл генерацию планет источниками



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

    5bbd22bc10be0483291405.png
    Ответ написан
    2 комментария
  • Запуск анимации только когда человек доскролил?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Вот вариант без сторонних библиотек. Для просмотра демки перейдите во вкладку [Result] и покрутите на нем колесико мышки вверх и вниз.

    Ответ написан
    7 комментариев