• Как регулярно отправлять HTTP-запросы?

    lastuniverse
    @lastuniverse
    Телега же работет без вэбсокетов?)
  • Как регулярно отправлять HTTP-запросы?

    lastuniverse
    @lastuniverse
    Jintsuu, организуй запрос статуса сразу для всех сообщений имеющихся в настоящий момент одним запросом.
    Например в сетинтервале отправляй массив с id интересующих сообщений, а с сервера возращай массив статусов, а еще лучше не в сет интервал а в обработчике предыдущего запроса через сеттаймоут
  • Как на node js (express) обрабатывать и логировать ошибки?

    lastuniverse
    @lastuniverse
    hOtRush, стандарты? А с чего вы взяли, что типовое решение из php является стандартом?

    Если же копнуть глубже, то мы легко сможем нагуглить, что экспресс это не мегокомбайн типа ларавеля, а легковесный вэб фреймворк, решение специфических задачь в котором как раз отданно на откуп различным сторонним библиотекам. Если уж на то пошло, существуюи в ноде и болеее жесткосвязанные фрэймворки, умеющие все из коробки. Например impress. Поэтому умерьте свой гонор, и избавляйтесь от привычки судить и советовать в вопросах, в которых вы не являетесь специалистом. Вы ведь не являетесь специалистом по фреймворкам представленным в экосистеме nodejs?
  • Как на node js (express) обрабатывать и логировать ошибки?

    lastuniverse
    @lastuniverse
    hOtRush, php изначально родился как результат костылестроения.

    В 1995 году датский программист (ныне живущий в Канаде) Расмус Лердорф (Rasmus Lerdorf) создал набор скриптов на Perl/CGI для вывода и учёта посетителей его онлайн-резюме, обрабатывающий шаблоны HTML-документов. Лердорф назвал набор Personal Home Page (Личная Домашняя Страница)
  • Чем заменить eval для простых выражений?

    lastuniverse
    @lastuniverse
    dollar, да, так и задумано, только один косячек в самой либе. Завтра исправлю. Сегодня уже сил нет.

    ЗЫ: пока не выходит каменный цветок. Но обязательно выйдет.

    ЗЫЗЫ: глубоко залип. спасаю библиотеку. как сделаю - отпишусь.
  • Чем заменить eval для простых выражений?

    lastuniverse
    @lastuniverse
    dollar, очень извиняюсь перед Вами, ввел Вас в заблуждение, данный код некорректно обрабатывает вложенные скобки. Работаю над этим.

    ЗЫ: с удивлением обнаружил что в js regexp-ах нет ни рекурсии ни балансировки.
  • Почему не срабатывает код?

    lastuniverse
    @lastuniverse
    Григорий, потому что setTimeout(hide, 2000); вы вызываете 1 раз, а при повторном открытии он уже не вызывается. Дал вам ответ, смотрите там.
  • Почему не срабатывает код?

    lastuniverse
    @lastuniverse
    1. Что вы имеете ввиду под первым и вторым открытием? Открытие окна (вкладки) браузера со страницей? Открытие модального окна?
    2. хз, не интересно лопатить код целой страницы.
  • Как на node js (express) обрабатывать и логировать ошибки?

    lastuniverse
    @lastuniverse
    hOtRush, иди дальше ковыряй PHP. Дивергентное мышление, не твой конек!
  • Чем заменить eval для простых выражений?

    lastuniverse
    @lastuniverse
    dollar, подправил код:

    код
    const Splitter = require("split-tools");
    
    var text = "x > 5 && (y == 7.5) || sin(PI*a/360) || isNumber(y) && true ";
    // var text = "x+-y"; // это тоже работает
    
    
    const splitter = new Splitter({
        matchers: {
            function: /\s*([a-z]\w*)\(\s*(.*)\s*\)/g,
            bracket: /\(\s*(.*)\s*\)/g,
            operator: /\s*(\!|\*|\/|\%|\+|\-|\=\=\=|\!\=\=|\<\=|\<|\>\=|\>|\=\=|\!\=|\&\&|\|\||\&|\|)\s*/g,
            boolean: /\s*(true|false)\s*/gi,
            sting: /\s*\"(.*?)\"\s*/gi,
            variable: /\s*([a-z][\w\.]*)\s*/gi,
            value: /\s*(\d[\d\.]*)\s*/gi
        }
    });
    
    const tree = {
        "brackets": ["function", "bracket", "operator", "boolean", "variable", "sting", "value"]
    };
     
    function subSplit(id, text) {
        console.log("subSplit:", id, "[", text, "]");
        if(tree[id] && tree[id].length)
            return splitter.process(text, tree[id]);
        return text;
    }
     
     
    splitter.addParser("function",(match,name,body)=>{
        return {
            type: "function",
            name: name,
            body: subSplit("brackets", body)
        };
    });
    
    splitter.addParser("bracket",(match,body)=>{
        return {
            type: "bracket",
            body: subSplit("brackets", body)
        };
    });
    
    splitter.addParser("operator",(match,body)=>{
        return {
            type: "operator",
            body: body
        };
    });
    
    splitter.addParser("variable",(match,body)=>{
        return {
            type: "variable",
            body: body
        };
    });
    
    splitter.addParser("string",(match,body)=>{
        return {
            type: "string",
            body: body
        };
    });
    
    splitter.addParser("boolean",(match,body)=>{
        return {
            type: "boolean",
            body: body==="true"?true:false
        };
    });
    
    splitter.addParser("value",(match,body)=>{
        return {
            type: "value",
            body: +body
        };
    });
     
     
    const list = splitter.process(text, tree.brackets);
     
    console.log("\n\nresult:\n",JSON.stringify(list, null, '  '));
    
    
    
    
    
    
    
    // тут я не придумал ничего умнее :)))
    var OPERATOR_PRIORITY = {
        '!': (src, dst)=>{    dst.push({type: "value", body: !src.shift()}) },
        '*': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body*src.shift().body} },
        '/': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body/src.shift().body} },
        '%': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body%src.shift().body} },
        '-': (src, dst)=>{    dst[dst.length-1] = {type: "operator",  body: "+" }; dst.push({type: "value", body: 0-src.shift().body}) },
        '+': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body+src.shift().body} },
        '<': (src, dst)=>{    dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body<src.shift().body?true:false) } },
        '<=': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body<=src.shift().body?true:false) } },
        '>': (src, dst)=>{    dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body>src.shift().body?true:false) } },
        '>=': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body>=src.shift().body?true:false) } },
        '==': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body==src.shift().body?true:false) } },
        '!=': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body!=src.shift().body?true:false) } },
        '===': (src, dst)=>{  dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body===src.shift().body?true:false) } },
        '!==': (src, dst)=>{  dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body!==src.shift().body?true:false) } },
        '&': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body&src.shift().body} },
        '|': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body|src.shift().body} },
        '&&': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body&&src.shift().body) } },
        '||': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body||src.shift().body) } }
    };
    
    
    // это набор разрешенных функций
    var ALLOWED_FUNCTIONS = {
        "sin": (v)=>{ return {type: "value", body: Math.sin(v)} },
        "cos": (v)=>{ return {type: "value", body: Math.cos(v)} },
        "isNumber": (v)=>{ return {type: "boolean", body: !isNaN(parseFloat(v)) && isFinite(v) } }
    };
    // это набор разрешенных переменных
    var ALLOWED_VARIABLES = {
        "PI": Math.PI,
        "x": 6,
        "y": 7.5,
        "a": 180
    };
    
    
    // парсер результатов разбора строки
    function resCalc(src){
    	
        src = src
    	// 	заменяем переменные на их значения
        .map(item=>{
            // если не переменная возвращаем как есть
            if(item.type !== "variable")
                return item;
                
            // иначе преобразуем переменную в ее значение
            // тут надо еще сделать проверку на наличие переменной в списке разрешенных
            const value = ALLOWED_VARIABLES[item.body];
            let type = "value";
            if( typeof value !== "number" ) type = typeof value;
            return {
                type: type,
                body: ALLOWED_VARIABLES[item.body]
            };
        })
    	// 	заменяем функции на их значения
        .map(item=>{
            // если не функция возвращаем как есть
            if(item.type !== "function")
                return item;
            // иначе преобразуем функции в ее значение
            // тут надо еще сделать проверку на наличие функции в списке разрешенных
            return ALLOWED_FUNCTIONS[item.name]( resCalc(item.body).body );
        })
    	// 	заменяем скобки на их значения
        .map(item=>{
            // если не переменная возвращаем как есть
            if(item.type !== "bracket")
                return item;
            // иначе преобразуем содержимое скобки в ее значение
            return resCalc(item.body);
        });
    
        let dst;
        Object.keys(OPERATOR_PRIORITY).forEach(operator=>{
            const _calc = OPERATOR_PRIORITY[operator];
            dst = [];
            while( src.length ){
                const item = src.shift();
                
        		 if(item.type === "operator" && item.body === operator){
                    // если оператор
                    // тут надо еще сделать проверку на наличие обработчика оператора
                    _calc(src, dst);
                }else{
                    // если все остальное
                    dst.push(item);
                }
                
            }
            src = dst;
        });
        return src[0];
    }
    
    console.log("\n\nresult:\n",JSON.stringify(resCalc(list), null, '  '));
    • унарный минус - реализован
    • добавление кастомных функций - реализовано
    • добавление кастомных переменных - реализовано
  • Чем заменить eval для простых выражений?

    lastuniverse
    @lastuniverse
    dollar, Вроде победил, правда для этого пошел путем обхода массива с результатами парсинга строки

    тестовая строка:
    "x > 5 && (y == 7.5) || sin(PI*a/360) || isNumber(y) && true "


    код
    const Splitter = require("split-tools");
    
    var text = "x > 5 && (y == 7.5) || sin(PI*a/360) || isNumber(y) && true ";
    // var text = "x > 5 && (y == 7.5) || sin(PI*a/360)";
    
    const splitter = new Splitter({
        matchers: {
            function: /\s*([a-z]\w*)\(\s*(.*)\s*\)/g,
            bracket: /\(\s*(.*)\s*\)/g,
            operator: /\s*(\!|\*|\/|\%|\+|\-|\=\=\=|\!\=\=|\<\=|\<|\>\=|\>|\=\=|\!\=|\&\&|\|\||\&|\|)\s*/g,
            boolean: /\s*(true|false)\s*/gi,
            sting: /\s*\"(.*?)\"\s*/gi,
            variable: /\s*([a-z][\w\.]*)\s*/gi,
            value: /\s*(\d[\d\.]*)\s*/gi
        }
    });
    
    const tree = {
        "brackets": ["function", "bracket", "operator", "boolean", "variable", "sting", "value"]
    };
     
    function subSplit(id, text) {
        console.log("subSplit:", id, "[", text, "]");
        if(tree[id] && tree[id].length)
            return splitter.process(text, tree[id]);
        return text;
    }
     
     
    splitter.addParser("function",(match,name,body)=>{
        return {
            type: "function",
            name: name,
            body: subSplit("brackets", body)
        };
    });
    
    splitter.addParser("bracket",(match,body)=>{
        return {
            type: "bracket",
            body: subSplit("brackets", body)
        };
    });
    
    splitter.addParser("operator",(match,body)=>{
        return {
            type: "operator",
            body: body
        };
    });
    
    splitter.addParser("variable",(match,body)=>{
        return {
            type: "variable",
            body: body
        };
    });
    
    splitter.addParser("string",(match,body)=>{
        return {
            type: "string",
            body: body
        };
    });
    
    splitter.addParser("boolean",(match,body)=>{
        return {
            type: "boolean",
            body: body==="true"?true:false
        };
    });
    
    splitter.addParser("value",(match,body)=>{
        return {
            type: "value",
            body: +body
        };
    });
     
     
    const list = splitter.process(text, tree.tags);
     
    console.log("\n\nresult:\n",JSON.stringify(list, null, '  '));
    
    
    
    
    // тут я не придумал ничего умнее :)))
    var OPERATOR_PRIORITY = {
        '!': (src, dst)=>{    dst.push({type: "value", body: !src.shift()}) },
        '*': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body*src.shift().body} },
        '/': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body/src.shift().body} },
        '%': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body%src.shift().body} },
        '-': (src, dst)=>{    dst[dst.length-1] = {type: "operator",  body: "+" }; dst.push({type: "value", body: 0-src.shift().body}) },
        '+': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body+src.shift().body} },
        '<': (src, dst)=>{    dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body<src.shift().body?true:false) } },
        '<=': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body<=src.shift().body?true:false) } },
        '>': (src, dst)=>{    dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body>src.shift().body?true:false) } },
        '>=': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body>=src.shift().body?true:false) } },
        '==': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body==src.shift().body?true:false) } },
        '!=': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body!=src.shift().body?true:false) } },
        '===': (src, dst)=>{  dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body===src.shift().body?true:false) } },
        '!==': (src, dst)=>{  dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body!==src.shift().body?true:false) } },
        '&': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body&src.shift().body} },
        '|': (src, dst)=>{    dst[dst.length-1] = {type: "value",     body: dst[dst.length-1].body|src.shift().body} },
        '&&': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body&&src.shift().body) } },
        '||': (src, dst)=>{   dst[dst.length-1] = {type: "boolean",   body: (dst[dst.length-1].body||src.shift().body) } }
    };
    
    
    // это набор разрешенных функций
    var ALLOWED_FUNCTIONS = {
        "sin": (v)=>{ return {type: "value", body: Math.sin(v)} },
        "cos": (v)=>{ return {type: "value", body: Math.cos(v)} },
        "isNumber": (v)=>{ return {type: "boolean", body: !isNaN(parseFloat(v)) && isFinite(v) } }
    };
    // это набор разрешенных переменных
    var ALLOWED_VARIABLES = {
        "PI": Math.PI,
        "x": 6,
        "y": 7.5,
        "a": 180
    };
    
    
    // парсер результатов разбора строки
    function resCalc(src){
    	// 	заменяем переменные на их значения
        src = src.map(item=>{
            // если не переменная возвращаем как есть
            if(item.type !== "variable")
                return item;
                
            // иначе преобразуем переменную в ее значение
            // тут надо еще сделать проверку на наличие переменной в списке разрешенных
            const value = ALLOWED_VARIABLES[item.body];
            let type = "value";
            if( typeof value !== "number" ) type = typeof value;
            return {
                type: type,
                body: ALLOWED_VARIABLES[item.body]
            };
        });
    
        let dst;
        Object.keys(OPERATOR_PRIORITY).forEach(operator=>{
            const _calc = OPERATOR_PRIORITY[operator];
            dst = [];
            while( src.length ){
                const item = src.shift();
    
                
                if(item.type === "function"){
                    // если функция
                    // тут надо еще сделать проверку на наличие функции в списке разрешенных
                    dst.push(ALLOWED_FUNCTIONS[item.name]( resCalc(item.body).body ) );
                }else if(item.type === "bracket"){
                    // если скобки
                    dst.push( resCalc(item.body).body );
                }else if(item.type === "operator" && item.body === operator){
                    // если оператор
                    // тут надо еще сделать проверку на наличие обработчика оператора
                    _calc(src, dst);
                }else{
                    // если все остальное
                    dst.push(item);
                }
                
            }
            src = dst;
        });
        return src[0];
    }
    
    
    console.log("\n\nresult:\n",JSON.stringify(resCalc(list), null, '  '));
    результат разбора
    [
      { "type": "variable", "body": "x" },
      { "type": "operator", "body": ">" },
      { "type": "value", "body": 5 },
      { "type": "operator", "body": "&&" },
      { "type": "bracket", "body": [
          { "type": "variable", "body": "y" },
          { "type": "operator", "body": "==" },
          { "type": "value", "body": 7.5 }
        ]
      },
      { "type": "operator", "body": "||" },
      { "type": "function", "name": "sin", "body": [
          { "type": "variable", "body": "PI" },
          { "type": "operator", "body": "*" },
          { "type": "variable",  "body": "a" },
          { "type": "operator", "body": "/" },
          { "type": "value", "body": 360 },
          { "type": "operator", "body": "||" },
          { "type": "variable", "body": "isNumber" },
          { "type": "variable", "body": "y" }
        ]
      },
      { "type": "operator", "body": "&&" },
      { "type": "boolean", "body": true }
    ]
    результат вычисления значения
    {
      "type": "boolean",
      "body": true
    }
  • Чем заменить eval для простых выражений?

    lastuniverse
    @lastuniverse
    dollar, еще немного подправил, добавил функции строки и булиевы значения
    Над обходом сейчас думаю, чтобы создало структуру, удобную для обхода с точки зрения приоритета операторов
  • Чем заменить eval для простых выражений?

    lastuniverse
    @lastuniverse
    dollar, Немного изменил свой ответ, вернее добавил в него способ решения Вашей задачи. Посмотрите все что после PS:
  • Можно ли при создании объекта использовать его же свойства?

    lastuniverse
    @lastuniverse
    При желании можно делать примерно так:

    let o = {
        x: 2
    };
    
    o.y = o.x;


    Но это уже не при создании)
  • Как сделать 2.5D игру html5?

    lastuniverse
    @lastuniverse
    Алексей Лебедев, вопрос с целевой аудиторией успешно решают единицы игровых стартапов из сотен а то и тысяч. Но по непроверенным данным )))) нынче народ склонен к играм, не привязывающим их к компу или телефону на длительное время (короткие катки, длительностью до 5 минут). Режим выживания идеально для этого подходит)
    Геймплей же, таких игр как один на все нарастающую, прущую на тебя толпу всегда очарователен, проверено такими монстрами как SeriosSam, тем же AlienShooter и их многочисленными клонами. Видимо основная масса игроков с удовольствием отказывается во время игры от каких либо проявлений мыслительного процесса, но при этом не прочь почувствовать себя супер героями ))))
  • Как отрисовать bullet, что-бы каждый клитент видел его?

    lastuniverse
    @lastuniverse
    Недавно на тостере уже спрашивали что-то такое Полёт пули в игре html5+js?

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