<commit_before>/*Copyright (c) 2013 Sripathi Pai
All rights reserved.
paisripathi at gmail dot com

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

String.prototype.count = function(ch){
    var i,c =0;
    if(typeof ch ==='string'){
        i = this.indexOf(ch);
        while(i != -1){
            c++;
            i = this.indexOf(ch,++i)
        }
        return c;
    }
    else {
        throw ("Type Error");

    }
    return c;

}

String.prototype.reverse = function() {
    return this.split('').reverse().join('');

}

String.prototype.title = function() {
    var a,i,l,s=[];
    a = this.trim().split(" ");
    l = a.length;
    for(i=0;i<l;i++){
        s.push(a[i].toString().replace(a[i][0],a[i][0].toUpperCase()));

    }

    return s.join(" ");

}

String.prototype.capitalize = function() {
    return this.toLowerCase().replace(this[0].toLowerCase(),this[0].toUpperCase());

}

String.prototype.isUpper = function() {
    var i=0;
     if(/(?=.*[a-z])/g.test(this)){
        return false;
     }
     return true;
}
String.prototype.isLower = function() {

    if((/(?=.*[A-Z])/g).test(this)) {
        return false;

    }

        return true;

}

String.prototype.swapCase = function() {
    var i,a=[],c='',l;
    a = this.split('');
    l = this.length;
    for(i=0;i<l;i++){
        if(a[i].isUpper()) {
            c = c+a[i].toUpperCase();

        }
        else {
            c = c+a[i].toLowerCase();
        }

    }
    return c;

}

String.prototype.isAlphaNum = function() {

    if((/\s/g).test(this)|| (/[^a-zA-Zs0-9]/g).test(this)){
        return false;

    }
    else {
        if((/\w\d/g).test(this)){
            return true;
        }

        else {
            return false;
        }

    }

}

String.prototype.contains = function(c)  {
    var re;
    re = new Regex(c,g);
    if(re.test(this)){
        return true;
    }
    else {
        return false;

    }

}

String.prototype.equals = function(s){
    var i=0,a,l;
    a = s.split('');
    l = s.length;
    if(l != this.length){
        return false;

    }
    else {
    while(i<l){
        if(this[i] != s[i]) {
            return false;

        }
        i++
    }
        return true;
    }

}

String.prototype.isEmpty = function() {

    if((/[\s\t\n]/g).test(this) || (this.length) ==0) {
        return true;

    }
    return false;
 }

String.prototype.isAlpha = function() {
    return !(/[^a-zA-Z]/g.test(this));

}

String.prototype.isDigit = function() {

    return !(/[^0-9]/g.test(this));
}

String.prototype.isTitle = function() {
    var i,l,s;
    a = this.split(" ");
    l = a.length;
    for (i=0;i<l;i++){
        if(!a[i][0].isUpper()){
            return false

        }

    }
    return true

}

<commit_msg>Added stripc method<commit_after>/*Copyright (c) 2013 Sripathi Pai
All rights reserved.
paisripathi at gmail dot com

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

String.prototype.count = function(ch){
    var i,c =0;
    if(typeof ch ==='string'){
        i = this.indexOf(ch);
        while(i != -1){
            c++;
            i = this.indexOf(ch,++i)
        }
        return c;
    }
    else {
        throw ("Type Error");

    }
    return c;

}

String.prototype.reverse = function() {
    return this.split('').reverse().join('');

}

String.prototype.title = function() {
    var a,i,l,s=[];
    a = this.trim().split(" ");
    l = a.length;
    for(i=0;i<l;i++){
        s.push(a[i].toString().replace(a[i][0],a[i][0].toUpperCase()));

    }

    return s.join(" ");

}

String.prototype.capitalize = function() {
    return this.toLowerCase().replace(this[0].toLowerCase(),this[0].toUpperCase());

}

String.prototype.isUpper = function() {
    var i=0;
     if(/(?=.*[a-z])/g.test(this)){
        return false;
     }
     return true;
}
String.prototype.isLower = function() {

    if((/(?=.*[A-Z])/g).test(this)) {
        return false;

    }

        return true;

}

String.prototype.swapCase = function() {
    var i,a=[],c='',l;
    a = this.split('');
    l = this.length;
    for(i=0;i<l;i++){
        if(a[i].isUpper()) {
            c = c+a[i].toUpperCase();

        }
        else {
            c = c+a[i].toLowerCase();
        }

    }
    return c;

}

String.prototype.isAlphaNum = function() {

    if((/\s/g).test(this)|| (/[^a-zA-Zs0-9]/g).test(this)){
        return false;

    }
    else {
        if((/\w\d/g).test(this)){
            return true;
        }

        else {
            return false;
        }

    }

}

String.prototype.contains = function(c)  {
    var re;
    re = new Regex(c,g);
    if(re.test(this)){
        return true;
    }
    else {
        return false;

    }

}

String.prototype.equals = function(s){
    var i=0,a,l;
    a = s.split('');
    l = s.length;
    if(l != this.length){
        return false;

    }
    else {
    while(i<l){
        if(this[i] != s[i]) {
            return false;

        }
        i++
    }
        return true;
    }

}

String.prototype.isEmpty = function() {

    if((/[\s\t\n]/g).test(this) || (this.length) ==0) {
        return true;

    }
    return false;
 }

String.prototype.isAlpha = function() {
    return !(/[^a-zA-Z]/g.test(this));

}

String.prototype.isDigit = function() {

    return !(/[^0-9]/g.test(this));
}

String.prototype.isTitle = function() {
    var i,l,s;
    a = this.split(" ");
    l = a.length;
    for (i=0;i<l;i++){
        if(!a[i][0].isUpper()){
            return false

        }

    }
    return true

}

String.prototype.stripc = function()  {
    var s=[],a='',l,i;
    s = this.split('');
    l = s.length;
    for(i=0;i<l;i++){
        if(/[a-zA-Z0-9]/g.test(s[i])){
            a = a+s[i];

        }

    }

    return a;

}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Thomas Kern
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

define(function (require, exports, module) {
    "use strict";

    exports.createPage = function (bodyText, messages, baseUrl, scrollPos, theme) {
        // Show URL in link tooltip
        bodyText = bodyText.replace(/(href=\"([^\"]*)\")/g, "$1 title=\"$2\"");
console.log(bodyText);
        // Assemble the HTML source
        var htmlSource = "";
        htmlSource += "<base href='" + baseUrl + "'>";
        htmlSource += "<link href='" + require.toUrl("../themes/" + theme + ".css") + "' rel='stylesheet'></link>";
        htmlSource += "<link href='" + require.toUrl("../styles/console.css") + "' rel='stylesheet'></link>";
        htmlSource += "<link href='" + require.toUrl("../styles/font-awesome/css/font-awesome.css") + "' rel='stylesheet'></link>";
        htmlSource += "<link href='" + require.toUrl("../styles/highlightjs/styles/googlecode.css") + "' rel='stylesheet'></link>";
        htmlSource += "";
        htmlSource += "";
        htmlSource += "";
        htmlSource += "
";
        htmlSource += bodyText + "
";

        if (messages.length) {
            htmlSource += '

'
            messages.forEach(function (msg) {
                htmlSource += msg + "
";
            });
            htmlSource += "

";
        }
        htmlSource += "";
        return htmlSource;
    };
});<commit_msg>logging statement removed<commit_after>/*
 * Copyright (c) 2014 Thomas Kern
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

define(function (require, exports, module) {
    "use strict";

    exports.createPage = function (bodyText, messages, baseUrl, scrollPos, theme) {
        // Show URL in link tooltip
        bodyText = bodyText.replace(/(href=\"([^\"]*)\")/g, "$1 title=\"$2\"");
        // Assemble the HTML source
        var htmlSource = "";
        htmlSource += "<base href='" + baseUrl + "'>";
        htmlSource += "<link href='" + require.toUrl("../themes/" + theme + ".css") + "' rel='stylesheet'></link>";
        htmlSource += "<link href='" + require.toUrl("../styles/console.css") + "' rel='stylesheet'></link>";
        htmlSource += "<link href='" + require.toUrl("../styles/font-awesome/css/font-awesome.css") + "' rel='stylesheet'></link>";
        htmlSource += "<link href='" + require.toUrl("../styles/highlightjs/styles/googlecode.css") + "' rel='stylesheet'></link>";
        htmlSource += "";
        htmlSource += "";
        htmlSource += "";
        htmlSource += "
";
        htmlSource += bodyText + "
";

        if (messages.length) {
            htmlSource += '

'
            messages.forEach(function (msg) {
                htmlSource += msg + "
";
            });
            htmlSource += "

";
        }
        htmlSource += "";
        return htmlSource;
    };
});
<|endoftext|>


<commit_before>'use strict'

const {dirname} = require('path')
const parse = require('./parse')
const debug = require('./debug')

const b64Regx = /(?<match>b64-{3}["']?(?<file>[\w.\-/:]+)["']?-{3})/gm

/**
 * @param {Object<Options>} options
 * @returns {Promise}
 */
function plugin(options = {}) {
	return {
		postcssPlugin: 'postcss-inline-base64',
		prepare(result) {
			const {to = process.cwd()} = result.opts
			options = {...{baseDir: dirname(to)}, ...options}

			debug.info('plugin | options ---> ', options)

			const inlines = new Set([])
			return {
				Declaration(node) {
					let matches
					while ((matches = b64Regx.exec(node.value)) !== null) {
						const {file, match} = matches.groups
						inlines.add(parse(file, match, node, options, result))
					}
				},
				RootExit() {
					return Promise.allSettled([...inlines])
				}
			}
		}
	}
}

module.exports = plugin

/**
 * @typedef Options                              - postcss-inline-base64 options
 * @property {String} [baseDir=process.cwd()]    - path to load files
 */
<commit_msg>fix regex<commit_after>'use strict'

const {dirname} = require('path')
const parse = require('./parse')
const debug = require('./debug')

const b64Regx = /(?<match>b64-{3}['"]?(?<file>[\w-./:]+)['"]?-{3})/g

/**
 * @param {Object<Options>} options
 * @returns {Promise}
 */
function plugin(options = {}) {
	return {
		postcssPlugin: 'postcss-inline-base64',
		prepare(result) {
			const {to = process.cwd()} = result.opts
			options = {...{baseDir: dirname(to)}, ...options}

			debug.info('plugin | options ---> ', options)

			const inlines = new Set([])
			return {
				Declaration(node) {
					let matches
					while ((matches = b64Regx.exec(node.value)) !== null) {
						const {file, match} = matches.groups
						inlines.add(parse(file, match, node, options, result))
					}
				},
				RootExit() {
					return Promise.allSettled([...inlines])
				}
			}
		}
	}
}

module.exports = plugin

/**
 * @typedef Options                              - postcss-inline-base64 options
 * @property {String} [baseDir=process.cwd()]    - path to load files
 */
<|endoftext|>


<commit_before>/**
 */
//
export class Pencil {

    // create Pencil.js instance
    // [[ CanvasRenderingContext2D ]]
    constructor(context2d) {
        this.ctx = context2d;
    }

    // clear whole frame
    // [[ ]]
    clear() {
        this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
    }

    // draw image to the canvas
    // [[ image, sx, sy, sw, sh, dx, dy, dw, dh, rad ]]
    drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, rad) {
        if (rad === 0) {
            this.ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
        }
        else {
            this.ctx.save();
            this.ctx.translate(dx + dw/2, dy + dh/2);
            this.ctx.rotate(rad);
            this.ctx.drawImage(image, sx, sy, sw, sh, -(dw/2), -(dh/2), dw, dh);
            this.ctx.restore();
        }
    }

    // complete path started with beginPath with a fill
    // [[ color ]]
    fill(c) {
        if (c !== undefined)
            this.ctx.fillStyle = c;
        this.ctx.fill();
    }

    // complete path started with beginPath with a stroke
    // [[ color ]]
    stroke(c) {
        if (c !== undefined)
            this.ctx.strokeStyle = c;
        this.ctx.stroke();
    }

    _getDrawMethod(m) {
        switch (m) {
            case 'stroke': return this.stroke.bind(this);
            case 'fill': return this.fill.bind(this);
            default: {
                console.warn(`'${m}' is not a valid Pencil drawing method`);
                return this.fill;
            }
        }
    }

    draw(m,c) {
        this._getDrawMethod(m)(c);
    }

    // integration for geometry.js
    // [[ shape, mode, color ]]
    drawShape(s, m, c) {
        switch (s.__proto__.constructor) {
            case Point: {
                this.drawRect(s.x, s.y, 1, 1, c, m);
                break;
            }
            case Circle: {
                this.ctx.beginPath();
                this.ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
                this.draw(m,c);
                break;
            }
            case Line: {
                this.ctx.beginPath();
                this.ctx.moveTo(s.pt1.x, s.pt1.y);
                this.ctx.lineTo(s.pt2.x, s.pt2.y);
                this.draw(m,c);
                break;
            }
            case Rectangle:
            case Square: {
                this.drawRect(s.x, s.y, s.width, s.height, m, c);
                break;
            }
            case Polygon: {
                this.drawPolygon(s.pts, m, c);
                break;
            }
        }
    }

    // draw an array of Points
    // [[ Array<Point>, mode, color ]]
    drawPolygon(pts, m, c) {
        this.ctx.beginPath();
        this.ctx.moveTo(pts[0].x, pts[0].y);
        pts.forEach((v) => {
            this.ctx.lineTo(v.x, v.y);
        });
        this.ctx.lineTo(pts[0].x, pts[0].y);
        this.draw(m,c);
    }

    // draw a rectangle
    // [[ x, y, width, height, mode, color ]]
    drawRect(x, y, w, h, m, c) {
        this.ctx.beginPath();
        this.ctx.rect(x,y,w,h);
        this.draw(m,c);
    }

    // draw Text
    // [[ x, y, mode, text, color, font ]]
    drawText(x, y, m, t, c, f) {
        if (c !== undefined)
            this.ctx[`${m}Style`] = c;
        if (f !== undefined)
            this.ctx.font = f;
        this.ctx[`${m}Text`](t, x, y);
    }
}
<commit_msg>Pencil: use constructor name in drawShape<commit_after>/**
 */
//
export class Pencil {

    // create Pencil.js instance
    // [[ CanvasRenderingContext2D ]]
    constructor(context2d) {
        this.ctx = context2d;
    }

    // clear whole frame
    // [[ ]]
    clear() {
        this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
    }

    // draw image to the canvas
    // [[ image, sx, sy, sw, sh, dx, dy, dw, dh, rad ]]
    drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, rad) {
        if (rad === 0) {
            this.ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
        }
        else {
            this.ctx.save();
            this.ctx.translate(dx + dw/2, dy + dh/2);
            this.ctx.rotate(rad);
            this.ctx.drawImage(image, sx, sy, sw, sh, -(dw/2), -(dh/2), dw, dh);
            this.ctx.restore();
        }
    }

    // complete path started with beginPath with a fill
    // [[ color ]]
    fill(c) {
        if (c !== undefined)
            this.ctx.fillStyle = c;
        this.ctx.fill();
    }

    // complete path started with beginPath with a stroke
    // [[ color ]]
    stroke(c) {
        if (c !== undefined)
            this.ctx.strokeStyle = c;
        this.ctx.stroke();
    }

    _getDrawMethod(m) {
        switch (m) {
            case 'stroke': return this.stroke.bind(this);
            case 'fill': return this.fill.bind(this);
            default: {
                console.warn(`'${m}' is not a valid Pencil drawing method`);
                return this.fill;
            }
        }
    }

    draw(m,c) {
        this._getDrawMethod(m)(c);
    }

    // integration for geometry.js
    // [[ shape, mode, color ]]
    drawShape(s, m, c) {
        switch (s.__proto__.constructor.name) {
            case 'Point': {
                this.drawRect(s.x, s.y, 1, 1, c, m);
                break;
            }
            case 'Circle': {
                this.ctx.beginPath();
                this.ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
                this.draw(m,c);
                break;
            }
            case 'Line': {
                this.ctx.beginPath();
                this.ctx.moveTo(s.pt1.x, s.pt1.y);
                this.ctx.lineTo(s.pt2.x, s.pt2.y);
                this.draw(m,c);
                break;
            }
            case 'Rectangle':
            case 'Square': {
                this.drawRect(s.x, s.y, s.width, s.height, m, c);
                break;
            }
            case 'Polygon': {
                this.drawPolygon(s.pts, m, c);
                break;
            }
        }
    }

    // draw an array of Points
    // [[ Array<Point>, mode, color ]]
    drawPolygon(pts, m, c) {
        this.ctx.beginPath();
        this.ctx.moveTo(pts[0].x, pts[0].y);
        pts.forEach((v) => {
            this.ctx.lineTo(v.x, v.y);
        });
        this.ctx.lineTo(pts[0].x, pts[0].y);
        this.draw(m,c);
    }

    // draw a rectangle
    // [[ x, y, width, height, mode, color ]]
    drawRect(x, y, w, h, m, c) {
        this.ctx.beginPath();
        this.ctx.rect(x,y,w,h);
        this.draw(m,c);
    }

    // draw Text
    // [[ x, y, mode, text, color, font ]]
    drawText(x, y, m, t, c, f) {
        if (c !== undefined)
            this.ctx[`${m}Style`] = c;
        if (f !== undefined)
            this.ctx.font = f;
        this.ctx[`${m}Text`](t, x, y);
    }
}
<|endoftext|>


<commit_before>var _ = require('_');

var _slice = (function(_slice) {
        return function(arr, start, end) {
            // Exit early for empty array
            if (!arr || !arr.length) { return []; }

            // End, naturally, has to be higher than 0 to matter,
            // so a simple existance check will do
            if (end) { return _slice.call(arr, start, end); }

            return _slice.call(arr, start || 0);
        };
    }([].slice)),

    // See jQuery
    // src\selector-native.js: 37
    _elementSort = (function() {

        var _hasDuplicate = false;
        var _sort = function(a, b) {
            // Flag for duplicate removal
            if (a === b) {
                _hasDuplicate = true;
                return 0;
            }

            var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition(b);

            // Not directly comparable, sort on existence of method
            if (!compare) { return a.compareDocumentPosition ? -1 : 1; }

            // Disconnected nodes
            if (compare & 1) {

                // Choose the first element that is related to our document
                if (a === document || b === document) { return 1; }

                // Maintain original order
                return 0;
            }

            return compare & 4 ? -1 : 1;
        };

        return function(array) {
            _hasDuplicate = false;
            array.sort(_sort);
            return _hasDuplicate;
        };

    }()),

    _unique = function(results) {
        var hasDuplicates = _elementSort(results);
        if (!hasDuplicates) { return results; }

        var elem,
            idx = 0,
            // create the array here
            // so that a new array isn't
            // created/destroyed every unique call
            duplicates = [];

        // Go through the array and identify
        // the duplicates to be removed
        while ((elem = results[idx++])) {
            if (elem === results[idx]) {
                duplicates.push(idx);
            }
        }

        // Remove the duplicates from the results
        idx = duplicates.length;
        while (idx--) {
           results.splice(duplicates[idx], 1);
        }

        return results;
    },

    _map = function(arr, iterator) {
        var results = [];
        if (!arr.length || !iterator) { return results; }

        var idx = 0, length = arr.length,
            item;
        for (; idx < length; idx++) {
            item = arr[idx];
            results.push(iterator.call(item, item, idx));
        }

        return _.concatFlat(results);
    },

    _each = function(obj, iterator) {
        if (!obj || !iterator) { return; }

        // Array support
        if (obj.length === +obj.length) {
            var idx = 0, length = obj.length,
                item;
            for (; idx < length; idx++) {
                item = obj[idx];
                if (iterator.call(item, item, idx) === false) { return; }
            }

            return;
        }

        // Object support
        var key, value;
        for (key in obj) {
            value = obj[key];
            if (iterator.call(value, value, key) === false) { return; }
        }
    };

module.exports = {
    slice: _slice,
    elementSort: _elementSort,
    unique: _unique,
    each: _each,

    fn: {
        // Determine the position of an element within
        // the matched set of elements
        index: function(elem) {

            // No argument, return index in parent
            if (!elem) {
                var first = this[0],
                    parent;
                return (first && (parent = first.parentNode)) ? _slice(parent.children).indexOf(first) : -1;
            }

            // index in selector
            /*if (_.isString(elem)) {
                return this.indexOf(this[0], jQuery( elem ) );
            }*/

            // Locate the position of the desired element
            return this.indexOf(elem instanceof D ? elem[0] : elem);
        },

        at: function(index) {
            return this[+index];
        },

        get: function(index) {
            // No index, return all
            if (!_.exists(index)) { return this.toArray(); }

            index = +index;

            // Looking to get an index from the end of the set
            if (index < 0) { index = (this.length + index); }

            return this[index];
        },

        eq: function(index) {
            return D(this.get(index));
        },

        slice: function(start, end) {
            return D(_slice(this.toArray(), start, end));
        },

        first: function() {
            return D(this[0]);
        },

        last: function() {
            return D(this[this.length - 1]);
        },

        toArray: function() {
            return _slice(this);
        },

        map: function(iterator) {
            return D(_map(this, iterator));
        },

        each: function(iterator) {
            _each(this, iterator);
            return this;
        },

        forEach: function(iterator) {
            _each(this, iterator);
            return this;
        }
    }
};<commit_msg>.index() enhancements (WIP)<commit_after>var _ = require('_'),
    _utils = require('../utils');

var _slice = (function(_slice) {
        return function(arr, start, end) {
            // Exit early for empty array
            if (!arr || !arr.length) { return []; }

            // End, naturally, has to be higher than 0 to matter,
            // so a simple existance check will do
            if (end) { return _slice.call(arr, start, end); }

            return _slice.call(arr, start || 0);
        };
    }([].slice)),

    // See jQuery
    // src\selector-native.js: 37
    _elementSort = (function() {

        var _hasDuplicate = false;
        var _sort = function(a, b) {
            // Flag for duplicate removal
            if (a === b) {
                _hasDuplicate = true;
                return 0;
            }

            var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition(b);

            // Not directly comparable, sort on existence of method
            if (!compare) { return a.compareDocumentPosition ? -1 : 1; }

            // Disconnected nodes
            if (compare & 1) {

                // Choose the first element that is related to our document
                if (a === document || b === document) { return 1; }

                // Maintain original order
                return 0;
            }

            return compare & 4 ? -1 : 1;
        };

        return function(array) {
            _hasDuplicate = false;
            array.sort(_sort);
            return _hasDuplicate;
        };

    }()),

    _unique = function(results) {
        var hasDuplicates = _elementSort(results);
        if (!hasDuplicates) { return results; }

        var elem,
            idx = 0,
            // create the array here
            // so that a new array isn't
            // created/destroyed every unique call
            duplicates = [];

        // Go through the array and identify
        // the duplicates to be removed
        while ((elem = results[idx++])) {
            if (elem === results[idx]) {
                duplicates.push(idx);
            }
        }

        // Remove the duplicates from the results
        idx = duplicates.length;
        while (idx--) {
           results.splice(duplicates[idx], 1);
        }

        return results;
    },

    _map = function(arr, iterator) {
        var results = [];
        if (!arr.length || !iterator) { return results; }

        var idx = 0, length = arr.length,
            item;
        for (; idx < length; idx++) {
            item = arr[idx];
            results.push(iterator.call(item, item, idx));
        }

        return _.concatFlat(results);
    },

    _each = function(obj, iterator) {
        if (!obj || !iterator) { return; }

        // Array support
        if (obj.length === +obj.length) {
            var idx = 0, length = obj.length,
                item;
            for (; idx < length; idx++) {
                item = obj[idx];
                if (iterator.call(item, item, idx) === false) { return; }
            }

            return;
        }

        // Object support
        var key, value;
        for (key in obj) {
            value = obj[key];
            if (iterator.call(value, value, key) === false) { return; }
        }
    };

module.exports = {
    slice: _slice,
    elementSort: _elementSort,
    unique: _unique,
    each: _each,

    fn: {
        // Determine the position of an element within
        // the matched set of elements
        index: function(elem) {

            // No argument, return index in parent
            if (!elem) {
                var first = this[0],
                    parent;
                // Note: _utils.isAttached check to pass test "Node without parent returns -1"
                return (first && (parent = first.parentNode) && _utils.isAttached(parent)) ? _slice(parent.children).indexOf(first) : -1;
            }

            // index in selector
            /*if (_.isString(elem)) {
                return this.indexOf(this[0], jQuery( elem ) );
            }*/

            // Locate the position of the desired element
            return this.indexOf(elem instanceof D ? elem[0] : elem);
        },

        at: function(index) {
            return this[+index];
        },

        get: function(index) {
            // No index, return all
            if (!_.exists(index)) { return this.toArray(); }

            index = +index;

            // Looking to get an index from the end of the set
            if (index < 0) { index = (this.length + index); }

            return this[index];
        },

        eq: function(index) {
            return D(this.get(index));
        },

        slice: function(start, end) {
            return D(_slice(this.toArray(), start, end));
        },

        first: function() {
            return D(this[0]);
        },

        last: function() {
            return D(this[this.length - 1]);
        },

        toArray: function() {
            return _slice(this);
        },

        map: function(iterator) {
            return D(_map(this, iterator));
        },

        each: function(iterator) {
            _each(this, iterator);
            return this;
        },

        forEach: function(iterator) {
            _each(this, iterator);
            return this;
        }
    }
};<|endoftext|>


<commit_before>const humanizeDuration = require("humanize-duration");
const moment = require("moment");
const blocked = require("../data/blocked");
const utils = require("../utils");

module.exports = ({ bot, knex, config, commands }) => {
  async function removeExpiredBlocks() {
    const expiredBlocks = await blocked.getExpiredBlocks();
    const logChannel = utils.getLogChannel();
    for (const userId of expiredBlocks) {
      await blocked.unblock(userId);
      logChannel.createMessage({
        content: `Block of <@!${userId}> (id \`${userId}\`) expired`,
        allowedMentions: {
          users: [userId],
        },
      });
    }
  }

  async function expiredBlockLoop() {
    try {
      await removeExpiredBlocks();
    } catch (e) {
      console.error(e);
    }

    setTimeout(expiredBlockLoop, 2000);
  }

  bot.on("ready", expiredBlockLoop);

  const blockCmd = async (msg, args, thread) => {
    const userIdToBlock = args.userId || (thread && thread.user_id);
    if (! userIdToBlock) return;

    const isBlocked = await blocked.isBlocked(userIdToBlock);
    if (isBlocked) {
      msg.channel.createMessage("User is already blocked");
      return;
    }

    const expiresAt = args.blockTime
      ? moment.utc().add(args.blockTime, "ms").format("YYYY-MM-DD HH:mm:ss")
      : null;

    const user = bot.users.get(userIdToBlock);
    await blocked.block(userIdToBlock, (user ? `${user.username}#${user.discriminator}` : ""), msg.author.id, expiresAt);

    if (expiresAt) {
      const humanized = humanizeDuration(args.blockTime, { largest: 2, round: true });
      msg.channel.createMessage(`Blocked <@${userIdToBlock}> (id \`${userIdToBlock}\`) from modmail for ${humanized}`);
    } else {
      msg.channel.createMessage(`Blocked <@${userIdToBlock}> (id \`${userIdToBlock}\`) from modmail indefinitely`);
    }
  };

  commands.addInboxServerCommand("block", "<userId:userId> [blockTime:delay]", blockCmd);
  commands.addInboxServerCommand("block", "[blockTime:delay]", blockCmd);

  const unblockCmd = async (msg, args, thread) => {
    const userIdToUnblock = args.userId || (thread && thread.user_id);
    if (! userIdToUnblock) return;

    const isBlocked = await blocked.isBlocked(userIdToUnblock);
    if (! isBlocked) {
      msg.channel.createMessage("User is not blocked");
      return;
    }

    const unblockAt = args.unblockDelay
      ? moment.utc().add(args.unblockDelay, "ms").format("YYYY-MM-DD HH:mm:ss")
      : null;

    const user = bot.users.get(userIdToUnblock);
    if (unblockAt) {
      const humanized = humanizeDuration(args.unblockDelay, { largest: 2, round: true });
      await blocked.updateExpiryTime(userIdToUnblock, unblockAt);
      msg.channel.createMessage(`Scheduled <@${userIdToUnblock}> (id \`${userIdToUnblock}\`) to be unblocked in ${humanized}`);
    } else {
      await blocked.unblock(userIdToUnblock);
      msg.channel.createMessage(`Unblocked <@${userIdToUnblock}> (id ${userIdToUnblock}) from modmail`);
    }
  };

  commands.addInboxServerCommand("unblock", "<userId:userId> [unblockDelay:delay]", unblockCmd);
  commands.addInboxServerCommand("unblock", "[unblockDelay:delay]", unblockCmd);

  commands.addInboxServerCommand("is_blocked",  "[userId:userId]",async (msg, args, thread) => {
    const userIdToCheck = args.userId || (thread && thread.user_id);
    if (! userIdToCheck) return;

    const blockStatus = await blocked.getBlockStatus(userIdToCheck);
    if (blockStatus.isBlocked) {
      if (blockStatus.expiresAt) {
        msg.channel.createMessage({
          content: `<@!${userIdToCheck}> (id \`${userIdToCheck}\`) is blocked until ${blockStatus.expiresAt} (UTC)`,
          allowedMentions: { users: [userIdToCheck] },
        });
      } else {
        msg.channel.createMessage({
          content: `<@!${userIdToCheck}> (id \`${userIdToCheck}\`) is blocked indefinitely`,
          allowedMentions: { users: [userIdToCheck] },
        });
      }
    } else {
      msg.channel.createMessage({
        content: `<@!${userIdToCheck}> (id \`${userIdToCheck}\`) is NOT blocked`,
        allowedMentions: { users: [userIdToCheck] },
      });
    }
  });
};
<commit_msg>Start expiredBlockLoop() directly, not on "ready" event<commit_after>const humanizeDuration = require("humanize-duration");
const moment = require("moment");
const blocked = require("../data/blocked");
const utils = require("../utils");

module.exports = ({ bot, knex, config, commands }) => {
  async function removeExpiredBlocks() {
    const expiredBlocks = await blocked.getExpiredBlocks();
    const logChannel = utils.getLogChannel();
    for (const userId of expiredBlocks) {
      await blocked.unblock(userId);
      logChannel.createMessage({
        content: `Block of <@!${userId}> (id \`${userId}\`) expired`,
        allowedMentions: {
          users: [userId],
        },
      });
    }
  }

  async function expiredBlockLoop() {
    try {
      await removeExpiredBlocks();
    } catch (e) {
      console.error(e);
    }

    setTimeout(expiredBlockLoop, 2000);
  }

  expiredBlockLoop();

  const blockCmd = async (msg, args, thread) => {
    const userIdToBlock = args.userId || (thread && thread.user_id);
    if (! userIdToBlock) return;

    const isBlocked = await blocked.isBlocked(userIdToBlock);
    if (isBlocked) {
      msg.channel.createMessage("User is already blocked");
      return;
    }

    const expiresAt = args.blockTime
      ? moment.utc().add(args.blockTime, "ms").format("YYYY-MM-DD HH:mm:ss")
      : null;

    const user = bot.users.get(userIdToBlock);
    await blocked.block(userIdToBlock, (user ? `${user.username}#${user.discriminator}` : ""), msg.author.id, expiresAt);

    if (expiresAt) {
      const humanized = humanizeDuration(args.blockTime, { largest: 2, round: true });
      msg.channel.createMessage(`Blocked <@${userIdToBlock}> (id \`${userIdToBlock}\`) from modmail for ${humanized}`);
    } else {
      msg.channel.createMessage(`Blocked <@${userIdToBlock}> (id \`${userIdToBlock}\`) from modmail indefinitely`);
    }
  };

  commands.addInboxServerCommand("block", "<userId:userId> [blockTime:delay]", blockCmd);
  commands.addInboxServerCommand("block", "[blockTime:delay]", blockCmd);

  const unblockCmd = async (msg, args, thread) => {
    const userIdToUnblock = args.userId || (thread && thread.user_id);
    if (! userIdToUnblock) return;

    const isBlocked = await blocked.isBlocked(userIdToUnblock);
    if (! isBlocked) {
      msg.channel.createMessage("User is not blocked");
      return;
    }

    const unblockAt = args.unblockDelay
      ? moment.utc().add(args.unblockDelay, "ms").format("YYYY-MM-DD HH:mm:ss")
      : null;

    const user = bot.users.get(userIdToUnblock);
    if (unblockAt) {
      const humanized = humanizeDuration(args.unblockDelay, { largest: 2, round: true });
      await blocked.updateExpiryTime(userIdToUnblock, unblockAt);
      msg.channel.createMessage(`Scheduled <@${userIdToUnblock}> (id \`${userIdToUnblock}\`) to be unblocked in ${humanized}`);
    } else {
      await blocked.unblock(userIdToUnblock);
      msg.channel.createMessage(`Unblocked <@${userIdToUnblock}> (id ${userIdToUnblock}) from modmail`);
    }
  };

  commands.addInboxServerCommand("unblock", "<userId:userId> [unblockDelay:delay]", unblockCmd);
  commands.addInboxServerCommand("unblock", "[unblockDelay:delay]", unblockCmd);

  commands.addInboxServerCommand("is_blocked",  "[userId:userId]",async (msg, args, thread) => {
    const userIdToCheck = args.userId || (thread && thread.user_id);
    if (! userIdToCheck) return;

    const blockStatus = await blocked.getBlockStatus(userIdToCheck);
    if (blockStatus.isBlocked) {
      if (blockStatus.expiresAt) {
        msg.channel.createMessage({
          content: `<@!${userIdToCheck}> (id \`${userIdToCheck}\`) is blocked until ${blockStatus.expiresAt} (UTC)`,
          allowedMentions: { users: [userIdToCheck] },
        });
      } else {
        msg.channel.createMessage({
          content: `<@!${userIdToCheck}> (id \`${userIdToCheck}\`) is blocked indefinitely`,
          allowedMentions: { users: [userIdToCheck] },
        });
      }
    } else {
      msg.channel.createMessage({
        content: `<@!${userIdToCheck}> (id \`${userIdToCheck}\`) is NOT blocked`,
        allowedMentions: { users: [userIdToCheck] },
      });
    }
  });
};
<|endoftext|>


<commit_before>module.exports = Parser;

var FileStructure = require('./file'),
	MonicError = require('./error');

var fs = require('fs'),
	path = require('path');

var async = require('async'),
	glob = require('glob');

/**
 * Объект парсера файла
 *
 * @constructor
 * @param {!Object} params - дополнительные параметры операции
 * @param {string} params.lineSeparator - символ перевода строки
 * @param {!Array} params.replacers - массив функций трансформации
 */
function Parser(params) {
	this.nl = params.lineSeparator;
	this.replacers = params.replacers || [];
	this.realpathCache = {};
	this.cache = {};
}

/**
 * Проверить существование указанного файла
 * и вернуть абсолютный путь к нему
 *
 * @param {string} file - адрес файла
 * @param {function(Error, string=)} callback - функция обратного вызова
 */
Parser.prototype.normalizePath = function (file, callback) {
	if (this.realpathCache[file]) {
		callback(null, this.realpathCache[file]);

	} else {
		async.waterfall([
			(callback) => {
				fs.exists(file, (exists) => {
					callback(null, exists);
				});
			},

			(exists, callback) => {
				if (!exists) {
					return callback(new Error(`File ${file} not found`));
				}

				fs.realpath(file, callback);
			},

			(src, callback) => {
				fs.stat(file, (err, stat) => {
					callback(err, stat, src.replace(/\\/g, '/'));
				});
			},

			(stat, src, callback) => {
				if (!stat.isFile()) {
					return callback(new Error(`File ${file} not found`));
				}

				this.realpathCache[file] = src;
				callback(null, src);
			}

		], callback);
	}
};

/**
 * Провести парсинг указанного файла
 * и вернуть его структуру
 *
 * @param {string} file - адрес файла
 * @param {function(Error, FileStructure=, string=)} callback - функция обратного вызова
 */
Parser.prototype.parseFile = function (file, callback) {
	this.normalizePath(file, (err, src) => {
		if (err) {
			return callback(err);
		}

		if (this.cache[src]) {
			return callback(null, this.cache[src], src);
		}

		fs.readFile(src, 'utf8', (err, content) => {
			if (err) {
				return callback(err);
			}

			this.parse(src, content, callback);
		});
	});
};

/**
 * Провести парсинг заданного текста
 * и вернуть его структуру
 *
 * @param {string} file - адрес файла
 * @param {string} content - содержимое файла
 * @param {function(Error, FileStructure=, string=)} callback - функция обратного вызова
 */
Parser.prototype.parse = function (file, content, callback) {
	if (this.cache[file]) {
		return callback(null, this.cache[file], file);
	}

	var actions = [],
		dirname = path.dirname(file);

	content = content.replace(/^(\s*\/\/#include\s+)(.*)/gm, (sstr, decl, src) => {
		if (/\*/.test(src)) {
			actions.push((callback) => {
				var parts = src.split('::');
				glob(path.join(dirname, parts[0]), null, (err, files) => {
					if (files) {
						content = content.replace(sstr, files.reduce((res, el) => {
							parts[0] = path.relative(dirname, el);
							res += decl + parts.join('::') + this.nl;
							return res;
						}, ''));
					}

					callback(err, files);
				});
			});
		}

		return sstr;
	});

	async.parallel(actions, (err) => {
		if (err) {
			return callback(err);
		}

		content = this.replacers.reduce((content, el) => {
			content = el(content);
			return content;

		}, content);

		var fileStructure = new FileStructure(file, this.nl),
			lines = content.split(/\r?\n|\r/);

		this.cache[file] = fileStructure;

		var parseLines = (start) => {
			var errors = [],
				i;

			function appendError(err) {
				var msg = err.message,
					line = i + 1;

				errors.push(new MonicError(msg, file, line));
				fileStructure.error(msg);
			}

			function asyncParseCallback(err) {
				if (err) {
					appendError(err);
				}

				parseLines(i + 1);
			}

			for (i = start; i < lines.length; i++) {
				let line = lines[i];

				if (line.match(/^\s*\/\/#(.*)/)) {
					if (RegExp.$1) {
						let command = RegExp.$1.split(' '),
							dir = String(command.shift());

						let key = '_' + dir,
							params = command.join(' ');

						if (/^(include|without)$/.test(dir)) {
							return this[key](fileStructure, params, asyncParseCallback);

						} else if (/^(label|endlabel|if|endif|set|unset)$/.test(dir)) {
							try {
								this[key](fileStructure, params);

							} catch (err) {
								appendError(err);
							}

						} else {
							appendError(new Error(`Unknown directive ${dir}`));
						}
					}

				} else {
					fileStructure.addCode(line + (i < lines.length - 1 ? this.nl : ''));
				}
			}

			callback(null, fileStructure, file);
		};

		parseLines(0);
	});
};

/**
 * Директива #include
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} params - параметры директивы
 * @param {function(Error=)} callback - функция обратного вызова
 */
Parser.prototype._include = function (file, params, callback) {
	var paramsParts = params.split('::'),
		includeFileName = paramsParts.shift();

	if (includeFileName) {
		let src = file.getRelativePathOf(includeFileName);
		this.parseFile(src, (err, includeFile) => {
			if (err) {
				return callback(err);
			}

			file.addInclude(includeFile, paramsParts);
			callback();
		});

	} else {
		try {
			file.addInclude(file, paramsParts);
			callback();

		} catch (err) {
			callback(err);
		}
	}
};

/**
 * Директива #without
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 * @param {function(Error=)} callback - функция обратного вызова
 */
Parser.prototype._without = function (file, value, callback) {
	var paramsParts = value.split('::'),
		includeFname = file.getRelativePathOf(paramsParts.shift());

	this.parseFile(includeFname, (err, includeFile) => {
		if (err) {
			return callback(err);
		}

		file.addWithout(includeFile, paramsParts);
		callback();
	});
};

/**
 * Директива #label
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 */
Parser.prototype._label = function (file, value) {
	file.beginLabel(value);
};

/**
 * Директива #endlabel
 * @param {!FileStructure} file - структура файла
 */
Parser.prototype._endlabel = function (file) {
	file.endLabel();
};

/**
 * Директива #if
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 */
Parser.prototype._if = function (file, value) {
	if (!value.trim()) {
		throw new Error('Bad "if" directive');
	}

	var args = value.split(/\s+/),
		res = true;

	if (args.length > 1 && args[0] === 'not') {
		res = false;
		args.shift();
	}

	file.beginIf(args[0], res);
};

/**
 * Директива #endif
 * @param {!FileStructure} file - структура файла
 */
Parser.prototype._endif = function (file) {
	file.endIf();
};

/**
 * Директива #set
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 */
Parser.prototype._set = function (file, value) {
	if (!value.trim()) {
		throw new Error('Bad set directive');
	}

	file.addSet(value.split(/\s+/)[0]);
};

/**
 * Директива #unset
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 */
Parser.prototype._unset = function (file, value) {
	if (!value.trim()) {
		throw new Error('Bad unset directive');
	}

	file.addUnset(value.split(/\s+/)[0]);
};
<commit_msg>Добавлены комментарии<commit_after>module.exports = Parser;

var FileStructure = require('./file'),
	MonicError = require('./error');

var fs = require('fs'),
	path = require('path');

var async = require('async'),
	glob = require('glob');

/**
 * Объект парсера файла
 *
 * @constructor
 * @param {!Object} params - дополнительные параметры операции
 * @param {string} params.lineSeparator - символ перевода строки
 * @param {!Array} params.replacers - массив функций трансформации
 */
function Parser(params) {
	this.nl = params.lineSeparator;
	this.replacers = params.replacers || [];
	this.realpathCache = {};
	this.cache = {};
}

/**
 * Проверить существование указанного файла
 * и вернуть абсолютный путь к нему
 *
 * @param {string} file - адрес файла
 * @param {function(Error, string=)} callback - функция обратного вызова
 */
Parser.prototype.normalizePath = function (file, callback) {
	if (this.realpathCache[file]) {
		callback(null, this.realpathCache[file]);

	} else {
		async.waterfall([
			(callback) => {
				fs.exists(file, (exists) => {
					callback(null, exists);
				});
			},

			(exists, callback) => {
				if (!exists) {
					return callback(new Error(`File ${file} not found`));
				}

				fs.realpath(file, callback);
			},

			(src, callback) => {
				fs.stat(file, (err, stat) => {
					callback(err, stat, src.replace(/\\/g, '/'));
				});
			},

			(stat, src, callback) => {
				if (!stat.isFile()) {
					return callback(new Error(`File ${file} not found`));
				}

				this.realpathCache[file] = src;
				callback(null, src);
			}

		], callback);
	}
};

/**
 * Провести парсинг указанного файла
 * и вернуть его структуру
 *
 * @param {string} file - адрес файла
 * @param {function(Error, FileStructure=, string=)} callback - функция обратного вызова
 */
Parser.prototype.parseFile = function (file, callback) {
	this.normalizePath(file, (err, src) => {
		if (err) {
			return callback(err);
		}

		if (this.cache[src]) {
			return callback(null, this.cache[src], src);
		}

		fs.readFile(src, 'utf8', (err, content) => {
			if (err) {
				return callback(err);
			}

			this.parse(src, content, callback);
		});
	});
};

/**
 * Провести парсинг заданного текста
 * и вернуть его структуру
 *
 * @param {string} file - адрес файла
 * @param {string} content - содержимое файла
 * @param {function(Error, FileStructure=, string=)} callback - функция обратного вызова
 */
Parser.prototype.parse = function (file, content, callback) {
	if (this.cache[file]) {
		return callback(null, this.cache[file], file);
	}

	var actions = [],
		dirname = path.dirname(file);

	// Обработка масок URL
	content = content.replace(/^(\s*\/\/#include\s+)(.*)/gm, (sstr, decl, src) => {
		if (/\*/.test(src)) {
			actions.push((callback) => {
				var parts = src.split('::');
				glob(path.join(dirname, parts[0]), null, (err, files) => {
					if (files) {
						content = content.replace(sstr, files.reduce((res, el) => {
							parts[0] = path.relative(dirname, el);
							res += decl + parts.join('::') + this.nl;
							return res;
						}, ''));
					}

					callback(err, files);
				});
			});
		}

		return sstr;
	});

	async.parallel(actions, (err) => {
		if (err) {
			return callback(err);
		}

		// Обработка перегрузок
		content = this.replacers.reduce((content, el) => {
			content = el(content);
			return content;

		}, content);

		var fileStructure = new FileStructure(file, this.nl),
			lines = content.split(/\r?\n|\r/);

		this.cache[file] = fileStructure;

		var parseLines = (start) => {
			var errors = [],
				i;

			function appendError(err) {
				var msg = err.message,
					line = i + 1;

				errors.push(new MonicError(msg, file, line));
				fileStructure.error(msg);
			}

			function asyncParseCallback(err) {
				if (err) {
					appendError(err);
				}

				parseLines(i + 1);
			}

			for (i = start; i < lines.length; i++) {
				let line = lines[i];

				if (line.match(/^\s*\/\/#(.*)/)) {
					if (RegExp.$1) {
						let command = RegExp.$1.split(' '),
							dir = String(command.shift());

						let key = '_' + dir,
							params = command.join(' ');

						if (/^(include|without)$/.test(dir)) {
							return this[key](fileStructure, params, asyncParseCallback);

						} else if (/^(label|endlabel|if|endif|set|unset)$/.test(dir)) {
							try {
								this[key](fileStructure, params);

							} catch (err) {
								appendError(err);
							}

						} else {
							appendError(new Error(`Unknown directive ${dir}`));
						}
					}

				} else {
					fileStructure.addCode(line + (i < lines.length - 1 ? this.nl : ''));
				}
			}

			callback(null, fileStructure, file);
		};

		parseLines(0);
	});
};

/**
 * Директива #include
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} params - параметры директивы
 * @param {function(Error=)} callback - функция обратного вызова
 */
Parser.prototype._include = function (file, params, callback) {
	var paramsParts = params.split('::'),
		includeFileName = paramsParts.shift();

	if (includeFileName) {
		let src = file.getRelativePathOf(includeFileName);
		this.parseFile(src, (err, includeFile) => {
			if (err) {
				return callback(err);
			}

			file.addInclude(includeFile, paramsParts);
			callback();
		});

	} else {
		try {
			file.addInclude(file, paramsParts);
			callback();

		} catch (err) {
			callback(err);
		}
	}
};

/**
 * Директива #without
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 * @param {function(Error=)} callback - функция обратного вызова
 */
Parser.prototype._without = function (file, value, callback) {
	var paramsParts = value.split('::'),
		includeFname = file.getRelativePathOf(paramsParts.shift());

	this.parseFile(includeFname, (err, includeFile) => {
		if (err) {
			return callback(err);
		}

		file.addWithout(includeFile, paramsParts);
		callback();
	});
};

/**
 * Директива #label
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 */
Parser.prototype._label = function (file, value) {
	file.beginLabel(value);
};

/**
 * Директива #endlabel
 * @param {!FileStructure} file - структура файла
 */
Parser.prototype._endlabel = function (file) {
	file.endLabel();
};

/**
 * Директива #if
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 */
Parser.prototype._if = function (file, value) {
	if (!value.trim()) {
		throw new Error('Bad "if" directive');
	}

	var args = value.split(/\s+/),
		res = true;

	if (args.length > 1 && args[0] === 'not') {
		res = false;
		args.shift();
	}

	file.beginIf(args[0], res);
};

/**
 * Директива #endif
 * @param {!FileStructure} file - структура файла
 */
Parser.prototype._endif = function (file) {
	file.endIf();
};

/**
 * Директива #set
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 */
Parser.prototype._set = function (file, value) {
	if (!value.trim()) {
		throw new Error('Bad set directive');
	}

	file.addSet(value.split(/\s+/)[0]);
};

/**
 * Директива #unset
 *
 * @param {!FileStructure} file - структура файла
 * @param {string} value - значение директивы
 */
Parser.prototype._unset = function (file, value) {
	if (!value.trim()) {
		throw new Error('Bad unset directive');
	}

	file.addUnset(value.split(/\s+/)[0]);
};
<|endoftext|>


<commit_before>/**
 * @license MPL 1.1/GPL 2.0/LGPL 2.1, see license.txt
 * @author William Elwood <we9@kent.ac.uk>
 * @copyright 2011 JSONovich Team. All Rights Reserved.
 * @copyright Portions (C) 2010 the Mozilla Foundation.
 * @description This file contains utilities for managing addon preferences specific to Gecko environments.
 * @todo When dropping Gecko 1.9.2/Firefox 3.6 support, remove emulation of Services.jsm.
 *
 * Changelog:
 * [2011-05] - Created preferences manager
 */

'use strict';

if(!("prefs" in Services)) { // emulate Services.jsm (introduced in Gecko 2/FF4)
    // @see http://hg.mozilla.org/mozilla-central/diff/78e5543c0bc4/toolkit/content/Services.jsm
    XPCOMUtils.defineLazyGetter(Services, "prefs", function () {
        return Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).QueryInterface(Ci.nsIPrefBranch2);
    });
}
if(!("contentPrefs" in Services)) {
    // @see http://hg.mozilla.org/mozilla-central/diff/3ccadf603301/toolkit/content/Services.jsm
    XPCOMUtils.defineLazyServiceGetter(Services, "contentPrefs", "@mozilla.org/content-pref/service;1", "nsIContentPrefService");
}
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";

/**
 * Preferences wrapped in a closure per branch
 */
exports.branch = function selectBranch(name, defaults) {
    if(!name || typeof name != 'string' || !name.length) {
        return null; // disallow root branch
    }
    if(name.charAt(name.length-1)!='.') {
        name += '.';
    }
    let branch = defaults ? Services.prefs.getDefaultBranch(name) : Services.prefs.getBranch(name);
    let returnObj = {};

    if(defaults) {
        /**
         * Deletes the selected default branch and the user branch of the same name, please
         * use responsibly to handle uninstallation of the addon's own preferences only.
         */
        returnObj.uninstall = function deleteBranch() {
            branch.deleteBranch('');
        };
    } else {
        (function() {
            let listener = {
                callbacks: {},
                listening: false,
                observe: function(subject, topic, data) {
                    if(subject == branch && topic == NS_PREFBRANCH_PREFCHANGE_TOPIC_ID && listener.callbacks.hasOwnProperty(data)) {
                        listener.callbacks[data](returnObj, data);
                    }
                },
                start: function() {
                    listener.listening = true;
                    branch.QueryInterface(Ci.nsIPrefBranch2);
                    branch.addObserver('', listener, false);
                    require('unload').unload(listener.stop);
                },
                stop: function() {
                    if(branch) {
                        branch.removeObserver('', listener);
                    }
                    listener.callbacks = {};
                    listener.listening = false;
                }
            };

            /**
             * This function efficiently handles observing several preferences with their own
             * callbacks using a single preference listener on the branch.
             *
             * @usage listenPref(pref, callback): Execute callback whenever pref changes.
             * @param pref <string>  The preference to observe for changes.
             * @param callback <function>  A 2-parameter function to execute whenever the specified preference
             *                             in this branch is changed, parameters will be 1) the closure returned
             *                             from the original selectBranch call containing this preferences API
             *                             and 2) the name of the changed preference relative to the branch.
             *                             Any previous callback for this pref will be overwritten.
             *
             * @usage listenPref(pref): Remove callback stored for pref.
             * @param pref <string>  The preference to stop observing for changes.
             */
            returnObj.listen = function listenPref(pref, callback) {
                if(callback) {
                    callback(returnObj, pref);
                    listener.callbacks[pref] = callback;
                    if(!listener.listening) {
                        listener.start();
                    }
                } else {
                    delete listener.callbacks[pref];
                    for(let p in listener.callbacks) { // why is there no easier way to do this? :(
                        if(listener.callbacks.hasOwnProperty(p)) {
                            return; // still listening to another preference, don't stop
                        }
                    }
                    listener.stop();
                }
            };
        })();

        /**
         * @param pref <string>  The preference to get relative to the branch.
         * @param type <string>  The type of value to get (boolean, integer, string-ascii,
         *                       string-unicode, string-locale, file-abs, file-rel)
         * @return <bool|int|string|nsISupportsString|nsIPrefLocalizedString
         *              |nsILocalFile|nsIRelativeFilePref>
         *                       The requested value, or the default if not set, or throw exception if default not set.
         */
        returnObj.get = function getPref(pref, type) {
            switch(type) {
                case 'boolean':
                    return branch.getBoolPref(pref);
                case 'integer':
                    return branch.getIntPref(pref);
                case 'string-ascii':
                    return branch.getCharPref(pref);
                case 'string-unicode':
                    return branch.getComplexType(pref, Ci.nsISupportsString).data;
                case 'string-locale':
                    return branch.getComplexType(pref, Ci.nsIPrefLocalizedString).data;
                case 'file-abs':
                    return branch.getComplexType(pref, Ci.nsILocalFile).data;
                case 'file-rel':
                    return branch.getComplexType(pref, Ci.nsIRelativeFilePref).data;
                default:
                    log('Unexpected pref type "' + type + '" in getPref.');
                    return null;
            }
        };
    }

    /**
     * @param pref <string>  The preference to be set relative to the branch.
     * @param type <string>  The type of value to set (boolean, integer, string-ascii,
     *                       string-unicode, string-locale, file-abs, file-rel)
     * @param value <bool|int|string|nsISupportsString|nsIPrefLocalizedString
     *              |nsILocalFile|nsIRelativeFilePref>
     *                       The value to set.
     */
    returnObj.set = function setPref(pref, type, value) {
        switch(type) {
            case 'boolean':
                branch.setBoolPref(pref, value);
                break;
            case 'integer':
                branch.setIntPref(pref, value);
                break;
            case 'string-ascii':
                branch.setCharPref(pref, value);
                break;
            case 'string-unicode':
                if(typeof value == 'string') {
                    let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
                    str.data = value;
                    value = str;
                }
                prefs.setComplexValue(pref, Ci.nsISupportsString, value);
                break;
            case 'string-locale':
                if(typeof value == 'string') {
                    let pls = Cc["@mozilla.org/pref-localizedstring;1"].createInstance(Ci.nsIPrefLocalizedString);
                    pls.data = value;
                    value = pls;
                }
                prefs.setComplexValue(pref, Ci.nsIPrefLocalizedString, value);
                break;
            case 'file-abs':
                if(typeof value == 'string') {
                    let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
                    file.initWithPath(value);
                    value = file;
                }
                prefs.setComplexValue(pref, Ci.nsILocalFile, value);
                break;
            case 'file-rel':
                // see https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO#Relative_path_(nsIRelativeFilePref)
                prefs.setComplexValue(pref, Ci.nsIRelativeFilePref, value);
                break;
            default:
                log('Unexpected pref type "' + type + '" in setPref.');
                break;
        }
    };

    return returnObj;
}
<commit_msg>Improve API of prefs module.<commit_after>/**
 * @license MPL 1.1/GPL 2.0/LGPL 2.1, see license.txt
 * @author William Elwood <we9@kent.ac.uk>
 * @copyright 2011 JSONovich Team. All Rights Reserved.
 * @copyright Portions (C) 2010 the Mozilla Foundation.
 * @description This file contains utilities for managing addon preferences specific to Gecko environments.
 * @todo When dropping Gecko 1.9.2/Firefox 3.6 support, remove emulation of Services.jsm.
 *
 * Changelog:
 * [2011-05] - Created preferences manager
 */

'use strict';

if(!("prefs" in Services)) { // emulate Services.jsm (introduced in Gecko 2/FF4)
    // @see http://hg.mozilla.org/mozilla-central/diff/78e5543c0bc4/toolkit/content/Services.jsm
    XPCOMUtils.defineLazyGetter(Services, "prefs", function () {
        return Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).QueryInterface(Ci.nsIPrefBranch2);
    });
}
if(!("contentPrefs" in Services)) {
    // @see http://hg.mozilla.org/mozilla-central/diff/3ccadf603301/toolkit/content/Services.jsm
    XPCOMUtils.defineLazyServiceGetter(Services, "contentPrefs", "@mozilla.org/content-pref/service;1", "nsIContentPrefService");
}
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";

/**
 * Preferences wrapped in a closure per branch
 */
exports.branch = function selectBranch(name, defaults) {
    if(!name || typeof name != 'string' || !name.length) {
        return null; // disallow root branch
    }
    if(name.charAt(name.length-1)!='.') {
        name += '.';
    }
    let branch = defaults ? Services.prefs.getDefaultBranch(name) : Services.prefs.getBranch(name);
    let returnObj = {};

    if(defaults) {
        /**
         * Deletes the selected default branch and the user branch of the same name, please
         * use responsibly to handle uninstallation of the addon's own preferences only.
         */
        returnObj.uninstall = function deleteBranch() {
            branch.deleteBranch('');
        };
    } else {
        (function() {
            let listener = {
                callbacks: {},
                listening: false,
                observe: function(subject, topic, data) {
                    if(subject == branch && topic == NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) {
                        if(listener.callbacks.hasOwnProperty(data)) {
                            listener.callbacks[data](returnObj, data);
                        }
                        if(listener.callbacks.hasOwnProperty('')) {
                            for (let c in listener.callbacks['']) {
                                c(returnObj, data);
                            }
                        }
                    }
                },
                start: function() {
                    listener.listening = true;
                    branch.QueryInterface(Ci.nsIPrefBranch2);
                    branch.addObserver('', listener, false);
                    require('unload').unload(listener.stop);
                },
                stop: function() {
                    if(branch) {
                        branch.removeObserver('', listener);
                    }
                    listener.callbacks = {};
                    listener.listening = false;
                }
            };

            /**
             * This function efficiently handles observing several preferences with their own
             * callbacks using a single preference listener on the branch.
             *
             * @usage listenPref(pref, callback): Execute callback whenever pref changes.
             * @param pref <string>  The preference to observe for changes.
             * @param callback <function>  A 2-parameter function to execute whenever the specified preference
             *                             in this branch is changed, parameters will be 1) the closure returned
             *                             from the original selectBranch call containing this preferences API
             *                             and 2) the name of the changed preference relative to the branch.
             *                             Any previous callback for this pref will be overwritten.
             *
             * @usage listenPref(pref): Remove callback stored for pref.
             * @param pref <string>  The preference to stop observing for changes.
             */
            returnObj.listen = function listenPref(pref, callback) {
                if(callback) {
                    callback(returnObj, pref);
                    listener.callbacks[pref] = callback;
                    if(!listener.listening) {
                        listener.start();
                    }
                } else {
                    delete listener.callbacks[pref];
                    for(let p in listener.callbacks) { // why is there no easier way to do this? :(
                        if(listener.callbacks.hasOwnProperty(p)) {
                            return; // still listening to another preference, don't stop
                        }
                    }
                    listener.stop();
                }
            };
        })();

        /**
         * @param pref <string>  The preference to get relative to the branch.
         * @param type <string>  The type of value to get (boolean, integer, string-ascii,
         *                       string-unicode, string-locale, file-abs, file-rel)
         * @return <bool|int|string|nsISupportsString|nsIPrefLocalizedString
         *              |nsILocalFile|nsIRelativeFilePref>
         *                       The requested value, or the default if not set, or throw exception if default not set.
         */
        returnObj.get = function getPref(pref, type) {
            try {
                switch(type) {
                    case 'boolean':
                        return branch.getBoolPref(pref);
                    case 'integer':
                        return branch.getIntPref(pref);
                    case 'string-ascii':
                        return branch.getCharPref(pref);
                    case 'string-unicode':
                        return branch.getComplexType(pref, Ci.nsISupportsString).data;
                    case 'string-locale':
                        return branch.getComplexType(pref, Ci.nsIPrefLocalizedString).data;
                    case 'file-abs':
                        return branch.getComplexType(pref, Ci.nsILocalFile).data;
                    case 'file-rel':
                        return branch.getComplexType(pref, Ci.nsIRelativeFilePref).data;
                    default:
                        require('log').error('Unexpected pref type "' + type + '" in getPref.');
                        return null;
                }
            } catch(e) {
                if(e.name != 'NS_ERROR_UNEXPECTED') {
                    require('log').debug(e);
                }
                return null;
            }
        };

        returnObj.getChildList = function getChildPrefsList() {
            return branch.getChildList('', {});
        };

        returnObj.unset = function clearPref(pref) {
            try {
                branch.clearUserPref(pref);
            } catch(e) { // throws if pref non-existant in Gecko<6
            }
        };
    }

    /**
     * @param pref <string>  The preference to be set relative to the branch.
     * @param type <string>  The type of value to set (boolean, integer, string-ascii,
     *                       string-unicode, string-locale, file-abs, file-rel)
     * @param value <bool|int|string|nsISupportsString|nsIPrefLocalizedString
     *              |nsILocalFile|nsIRelativeFilePref>
     *                       The value to set.
     */
    returnObj.set = function setPref(pref, type, value) {
        switch(type) {
            case 'boolean':
                branch.setBoolPref(pref, value);
                break;
            case 'integer':
                branch.setIntPref(pref, value);
                break;
            case 'string-ascii':
                branch.setCharPref(pref, value);
                break;
            case 'string-unicode':
                if(typeof value == 'string') {
                    let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
                    str.data = value;
                    value = str;
                }
                prefs.setComplexValue(pref, Ci.nsISupportsString, value);
                break;
            case 'string-locale':
                if(typeof value == 'string') {
                    let pls = Cc["@mozilla.org/pref-localizedstring;1"].createInstance(Ci.nsIPrefLocalizedString);
                    pls.data = value;
                    value = pls;
                }
                prefs.setComplexValue(pref, Ci.nsIPrefLocalizedString, value);
                break;
            case 'file-abs':
                if(typeof value == 'string') {
                    let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
                    file.initWithPath(value);
                    value = file;
                }
                prefs.setComplexValue(pref, Ci.nsILocalFile, value);
                break;
            case 'file-rel':
                // see https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO#Relative_path_(nsIRelativeFilePref)
                prefs.setComplexValue(pref, Ci.nsIRelativeFilePref, value);
                break;
            default:
                require('log').error('Unexpected pref type "' + type + '" in setPref.');
                break;
        }
    };

    return returnObj;
}
<|endoftext|>


<commit_before>import { combineReducers, createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import counter from './counter/dux' // TODO: How to I get webpack to let me import like: import counter from 'counter/dux'
// http://moduscreate.com/es6-es2015-import-no-relative-path-webpack/
import todo from './todo/dux'
import drawer from './drawer/dux'

let store
const middleware = [ thunk ]

// if (__DEV__) {
//   const createLogger = require('redux-logger')
//   const logger = createLogger()
//   middleware.push(logger)
// }

function isStoreInitialized() {
  if (!store) {
    console.error('Store has not been initialized! Did you run configureStore?')
    return false
  }

  return true
}

export function configureStore() {
  const rootReducer = combineReducers({ counter, todo, drawer })
  store = createStore(rootReducer, applyMiddleware(...middleware))
  return store
}

export function dispatch(action) {
  if (!isStoreInitialized()) {
    return null
  }

  return store.dispatch(action)
}

export function getState() {
  if (!isStoreInitialized()) {
    return null
  }

  return store.getState()
}
<commit_msg>Plug in redux logger for dev<commit_after>import { combineReducers, createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import counter from './counter/dux' // TODO: How to I get webpack to let me import like: import counter from 'counter/dux'
// http://moduscreate.com/es6-es2015-import-no-relative-path-webpack/
import todo from './todo/dux'
import drawer from './drawer/dux'

let store
const middleware = [ thunk ]

if (process.env.ENVIRONMENT === 'development') {
  const createLogger = require('redux-logger')
  const logger = createLogger()
  middleware.push(logger)
}

function isStoreInitialized() {
  if (!store) {
    console.error('Store has not been initialized! Did you run configureStore?')
    return false
  }

  return true
}

export function configureStore() {
  const rootReducer = combineReducers({ counter, todo, drawer })
  store = createStore(rootReducer, applyMiddleware(...middleware))
  return store
}

export function dispatch(action) {
  if (!isStoreInitialized()) {
    return null
  }

  return store.dispatch(action)
}

export function getState() {
  if (!isStoreInitialized()) {
    return null
  }

  return store.getState()
}
<|endoftext|>


<commit_before>
const fs = require('fs')
const KEY = JSON.parse( fs.readFileSync(`${__dirname}/../secret/key.json`) )
const { URL, PUN } = JSON.parse( fs.readFileSync(`${__dirname}/../config.json`) )

const request = require('request')
const mysql = require('mysql')
const Twitter = require('twitter')
const cheerio = require('cheerio')

class Idol {
  constructor(tr) {
    this.id = tr.find('td.name > a').attr('href')
      .match(/c=([0-9]+)/)[1] * 1

    this.name = tr.find('td.name > a').text()
      .replace(/\[[0-9]+\]/, '')
      .replace(/【.*】/, '')
      .trim()

    // 등급
    this.grade = tr.find('td.field1').text().replace(/[0-9]/, '')
    // 속성
    this.type = tr.find('td.field2').text().replace(/[0-9]/, '')
    // 한정
    this.limited = tr.attr('field7') * 1

    this.img = this.grade.match('SR')
      ? URL.inven.img_src_style.replace('{id}', this.id)
      : null
  }
}

/**
 * 아이돌을 추가합니다.
 */
function insertIdol(idol) {
  const QUERY_IDOL_INSERT = `
    INSERT INTO idol(id, name, grade, type, limited, now, img_url)
    VALUES (?, ?, ?, ?, ?, ?, ?)
  `
  const QUERY_IDOL_UPDATE_NOW = `
    UPDATE idol
    SET now = ?
    WHERE name = ?
  `
  const param = [
    idol.id,
    idol.name,
    idol.grade,
    idol.type,
    idol.limited,
    0,
    idol.img
  ]

  const connection = mysql.createConnection( KEY.DB )
  connection.connect()
  connection.query(QUERY_IDOL_INSERT, param, (err, result) => {
    if (!err) console.log(`DB에 추가: ${idol.name}`)
    connection.query(QUERY_IDOL_UPDATE_NOW, [1, idol.name], (err, result) => {
      if (!err) console.log(`확률업 설정: ${idol.name}`)
      connection.end()
    })
  })
}

/**
 * 아이돌을 파싱합니다.
 */
function idolParse(newIdols) {
  const QUERY_IDOL_INIT_NOW = `
    UPDATE idol
    SET now = 0
  `
  const connection = mysql.createConnection( KEY.DB )
  connection.connect()
  connection.query(QUERY_IDOL_INIT_NOW, (err, result) => {
    connection.end()

    request(URL.inven.idol, (err, res, body) => {
      if (err) throw err

      const $ = cheerio.load(body)
      const idols = $('tr[field7]')

      idols.each((i, el) => {
        const idol = new Idol($(el))

        const now = newIdols.find(newIdol => {
          // 스페이스가 아닌 이상한 문자 고치기
          return idol.name == newIdol.replace(/\s/g, ' ')
        })

        if (now) insertIdol(idol)
      })
    })
  })
}

/**
 * 뉴스 리스트를 파싱합니다.
 */
function listParse() {
  return new Promise((resolve, reject) => {
    request(URL.inven.news, (err, res, body) => {

      const $ = cheerio.load(body)
      const list = $('td.bbsSubject')
        .filter((i, el) => $(el).text().match(/데레스테/))
        .filter((i, el) => $(el).text().match(/신규 아이돌|가챠/))

      const target = $(list[0]).text().match(/타입 셀렉트/)
        ? $(list[1])
        : $(list[0])

      resolve({
        title: target.text(),
        src: target.find('a').attr('href')
      })
    })
  })
}

/**
 * 뉴스를 파싱합니다.
 */
function newsParse(src) {
  return new Promise((resolve, reject) => {
    request(src, (err, res, body) => {

      const $ = cheerio.load(body, { decodeEntities: false })
      const title = $('.articleTitle').text()
      $('
\n
').insertBefore('#powerbbsContent br')
      $('
\n
').insertBefore('#powerbbsContent p')

      const content = $('#powerbbsContent').html()
        .split('스타 샤인')[0]
      const idolsText = content.split(/<.*?>/)
        .filter(str => str.match(/\[.*?\]/))

      const idols = []
      const ssrNames = []

      idolsText.forEach(str => {
        const ssr = str.match(/SS(R|레어)/)
        const idol = str.replace(/\(?S+(R|레어)\)?/, '').replace(/\(?CV.*\(?/, '').trim()
        const names = idol.replace(/\[.*\]/, '').trim().split(' ')

        idols.push(idol)
        if(ssr) ssrNames.push(names[1] || names[0])
      })

      const endDate = content.match(/[0-9]+월 [0-9]+일 [0-9]+:59/)[0]

      let type = '통상'
      if (title.match(/가챠.*개최/)) type = '한정'
      if (title.match(/재등장/)) type = '복각'

      resolve({
        type,
        idols,
        ssrNames,
        endDate
      })
    })
  })
}

/**
 * 다쟈레를 파싱합니다.
 */
function punParse() {
  const QUERY_PUN = `
    INSERT INTO pun(text, reg_dtime)
    VALUES (? , ?)
  `

  const twitter = new Twitter( KEY.TWITTER )
  const connection = mysql.createConnection( KEY.DB )
  connection.connect()

  twitter.get('statuses/user_timeline', PUN, (err, tweets, res) => {

    tweets.forEach(({text, created_at}) => {
      if( !text.match(/@.* /) ){
        text = text.replace(/https:.*/, '')
          .replace(/\(([A-Za-z0-9_]+)\)/, '(@$1)')
          .trim()

        connection.query(QUERY_PUN, [text, new Date(created_at)], (err, result) => {
          if (err) throw err
          else console.log( result.insertId )
        })
      }
    })
    connection.end()

  })
}

module.exports = {
  punParse,
  idolParse,
  gachaParse() {
    return listParse()
    .then(bbs => newsParse(bbs.src))
  }
}
<commit_msg>예고 제외<commit_after>
const fs = require('fs')
const KEY = JSON.parse( fs.readFileSync(`${__dirname}/../secret/key.json`) )
const { URL, PUN } = JSON.parse( fs.readFileSync(`${__dirname}/../config.json`) )

const request = require('request')
const mysql = require('mysql')
const Twitter = require('twitter')
const cheerio = require('cheerio')

class Idol {
  constructor(tr) {
    this.id = tr.find('td.name > a').attr('href')
      .match(/c=([0-9]+)/)[1] * 1

    this.name = tr.find('td.name > a').text()
      .replace(/\[[0-9]+\]/, '')
      .replace(/【.*】/, '')
      .trim()

    // 등급
    this.grade = tr.find('td.field1').text().replace(/[0-9]/, '')
    // 속성
    this.type = tr.find('td.field2').text().replace(/[0-9]/, '')
    // 한정
    this.limited = tr.attr('field7') * 1

    this.img = this.grade.match('SR')
      ? URL.inven.img_src_style.replace('{id}', this.id)
      : null
  }
}

/**
 * 아이돌을 추가합니다.
 */
function insertIdol(idol) {
  const QUERY_IDOL_INSERT = `
    INSERT INTO idol(id, name, grade, type, limited, now, img_url)
    VALUES (?, ?, ?, ?, ?, ?, ?)
  `
  const QUERY_IDOL_UPDATE_NOW = `
    UPDATE idol
    SET now = ?
    WHERE name = ?
  `
  const param = [
    idol.id,
    idol.name,
    idol.grade,
    idol.type,
    idol.limited,
    0,
    idol.img
  ]

  const connection = mysql.createConnection( KEY.DB )
  connection.connect()
  connection.query(QUERY_IDOL_INSERT, param, (err, result) => {
    if (!err) console.log(`DB에 추가: ${idol.name}`)
    connection.query(QUERY_IDOL_UPDATE_NOW, [1, idol.name], (err, result) => {
      if (!err) console.log(`확률업 설정: ${idol.name}`)
      connection.end()
    })
  })
}

/**
 * 아이돌을 파싱합니다.
 */
function idolParse(newIdols) {
  const QUERY_IDOL_INIT_NOW = `
    UPDATE idol
    SET now = 0
  `
  const connection = mysql.createConnection( KEY.DB )
  connection.connect()
  connection.query(QUERY_IDOL_INIT_NOW, (err, result) => {
    connection.end()

    request(URL.inven.idol, (err, res, body) => {
      if (err) throw err

      const $ = cheerio.load(body)
      const idols = $('tr[field7]')

      idols.each((i, el) => {
        const idol = new Idol($(el))

        const now = newIdols.find(newIdol => {
          // 스페이스가 아닌 이상한 문자 고치기
          return idol.name == newIdol.replace(/\s/g, ' ')
        })

        if (now) insertIdol(idol)
      })
    })
  })
}

/**
 * 뉴스 리스트를 파싱합니다.
 */
function listParse() {
  return new Promise((resolve, reject) => {
    request(URL.inven.news, (err, res, body) => {

      const $ = cheerio.load(body)
      const list = $('td.bbsSubject')
        .filter((i, el) => $(el).text().match(/데레스테/))
        .filter((i, el) => $(el).text().match(/신규 아이돌|가챠/))
        .filter((i, el) => !$(el).text().match(/예고/))

      const target = $(list[0]).text().match(/타입 셀렉트/)
        ? $(list[1])
        : $(list[0])

      resolve({
        title: target.text(),
        src: target.find('a').attr('href')
      })
    })
  })
}

/**
 * 뉴스를 파싱합니다.
 */
function newsParse(src) {
  return new Promise((resolve, reject) => {
    request(src, (err, res, body) => {

      const $ = cheerio.load(body, { decodeEntities: false })
      const title = $('.articleTitle').text()
      $('
\n
').insertBefore('#powerbbsContent br')
      $('
\n
').insertBefore('#powerbbsContent p')

      const content = $('#powerbbsContent').html()
        .split('스타 샤인')[0]
      const idolsText = content.split(/<.*?>/)
        .filter(str => str.match(/\[.*?\]/))

      const idols = []
      const ssrNames = []

      idolsText.forEach(str => {
        const ssr = str.match(/SS(R|레어)/)
        const idol = str.replace(/\(?S+(R|레어)\)?/, '').replace(/\(?CV.*\(?/, '').trim()
        const names = idol.replace(/\[.*\]/, '').trim().split(' ')

        idols.push(idol)
        if(ssr) ssrNames.push(names[1] || names[0])
      })

      const endDate = content.match(/[0-9]+월 [0-9]+일 [0-9]+:59/)[0]

      let type = '통상'
      if (title.match(/가챠.*개최/)) type = '한정'
      if (title.match(/재등장/)) type = '복각'

      resolve({
        type,
        idols,
        ssrNames,
        endDate
      })
    })
  })
}

/**
 * 다쟈레를 파싱합니다.
 */
function punParse() {
  const QUERY_PUN = `
    INSERT INTO pun(text, reg_dtime)
    VALUES (? , ?)
  `

  const twitter = new Twitter( KEY.TWITTER )
  const connection = mysql.createConnection( KEY.DB )
  connection.connect()

  twitter.get('statuses/user_timeline', PUN, (err, tweets, res) => {

    tweets.forEach(({text, created_at}) => {
      if( !text.match(/@.* /) ){
        text = text.replace(/https:.*/, '')
          .replace(/\(([A-Za-z0-9_]+)\)/, '(@$1)')
          .trim()

        connection.query(QUERY_PUN, [text, new Date(created_at)], (err, result) => {
          if (err) throw err
          else console.log( result.insertId )
        })
      }
    })
    connection.end()

  })
}

module.exports = {
  punParse,
  idolParse,
  gachaParse() {
    return listParse()
    .then(bbs => newsParse(bbs.src))
  }
}
<|endoftext|>


<commit_before>/**
 * Run Tests
 * Copyright (c) 2011 Reginaldo Silva (reginaldo@ubercomp.com)
 * Created: 30/11/11 23:39
 */
"use strict";

lm32.run_tests = function(wait_time, first_test, last_test) {
    if(! wait_time) {
        wait_time = 500;
    }
    var term_element = 'terminal';
    var tests = [
        'test_add.tst.bin',
        'test_addi.tst.bin',
        'test_and.tst.bin',
        'test_andhi.tst.bin',
        'test_andi.tst.bin',
        'test_b.tst.bin',
        'test_be.tst.bin',
        'test_bg.tst.bin',
        'test_bge.tst.bin',
        'test_bgeu.tst.bin',
        'test_bgu.tst.bin',
        'test_bi.tst.bin',
        'test_bne.tst.bin',
        'test_break.tst.bin',
        'test_bret.tst.bin',
        'test_call.tst.bin',
        'test_calli.tst.bin',
        'test_cmpe.tst.bin',
        'test_cmpei.tst.bin',
        'test_cmpg.tst.bin',
        'test_cmpge.tst.bin',
        'test_cmpgei.tst.bin',
        'test_cmpgeu.tst.bin',
        'test_cmpgeui.tst.bin',
        'test_cmpgi.tst.bin',
        'test_cmpgu.tst.bin',
        'test_cmpgui.tst.bin',
        'test_cmpne.tst.bin',
        'test_cmpnei.tst.bin',
        'test_divu.tst.bin',
        'test_eret.tst.bin',
        'test_lb.tst.bin',
        'test_lbu.tst.bin',
        'test_lh.tst.bin',
        'test_lhu.tst.bin',
        'test_lw.tst.bin',
        'test_modu.tst.bin',
        'test_mul.tst.bin',
        'test_muli.tst.bin',
        'test_nor.tst.bin',
        'test_nori.tst.bin',
        'test_or.tst.bin',
        'test_orhi.tst.bin',
        'test_ori.tst.bin',
        'test_ret.tst.bin',
        'test_sb.tst.bin',
        'test_scall.tst.bin',
        'test_sextb.tst.bin',
        'test_sexth.tst.bin',
        'test_sh.tst.bin',
        'test_sl.tst.bin',
        'test_sli.tst.bin',
        'test_sr.tst.bin',
        'test_sri.tst.bin',
        'test_sru.tst.bin',
        'test_srui.tst.bin',
        'test_sub.tst.bin',
        'test_sw.tst.bin',
        'test_xnor.tst.bin',
        'test_xnori.tst.bin',
        'test_xor.tst.bin',
        'test_xori.tst.bin'
    ];
    if(first_test === undefined) {
        first_test = 0;
    }
    if(last_test === undefined) {
        last_test = tests.length - 1;
    }
    console.log("Running tests " + first_test + " through " + last_test);
    var sys = lm32.start_sys(term_element);
    var i = first_test;
    var f = function() {
        sys.shutdown.value = false;
        sys.run_test(tests[i], i, sys.shutdown);
        i++;
        if(i <= last_test) {
            setTimeout(f, wait_time);
        }
    }
    f();
};

lm32.start_sys = function(terminal_div) {
    var RAM_BASE = 0x08000000;
    var RAM_SIZE = 1*1024*1024;
    var EBA_BASE = RAM_BASE;
    var DEBA_BASE = RAM_BASE;

    var TESTDEV_BASE = 0xffff0000;
    var MAX_STEPS = 1000;
    var BOOT_PC = RAM_BASE;

    var mmu = new lm32.MMU();

    var cpu_params = {
        mmu: mmu,
        bootstrap_pc: BOOT_PC,
        bootstrap_eba: EBA_BASE,
        bootstrap_deba: DEBA_BASE
    };
    var ram = new lm32.RAM(RAM_SIZE, true);

    var term = document.getElementById(terminal_div);
    var terminal = (function() {
        return {
          write: function(str) {
              term.textContent = term.textContent + str;
          }
        };
    })();

    terminal.write("LM32 Test Runner\n");

    var shutdown = { value: false };
    function shutdown_f() {
        terminal.write("Shutdown Requested!\n\n");
        shutdown.value = true;
    }

    var testdev_params = {
        mmu: mmu,
        shutdown: shutdown_f,
        terminal: terminal
    };
    var testdev = new lm32.TestDev(testdev_params);
    var DummyTimer = function() {
        this.on_tick = function() {};
    };
    var timer = new DummyTimer();

    mmu.add_memory(RAM_BASE, RAM_SIZE, ram.get_mmio_handlers());
    mmu.add_memory(TESTDEV_BASE, testdev.iomem_size, testdev.get_mmio_handlers());

    function run_test(test_name, idx, shutdown) {
        var cpu = new lm32.Lm32Cpu(cpu_params);
        cpu.set_timers([timer]);
        // testdev.reset();
        var str = "\nRunning Test " + test_name + " (" + idx + ")\n";
        terminal.write(str);
        console.log(str);
        mmu.log = false;
        mmu.load_binary("../test/" + test_name, BOOT_PC);
        mmu.log = true;
        var steps = 0;
        while(shutdown.value == false && steps < MAX_STEPS) {
            cpu.step(1);
            steps++;
        }
        if(shutdown.value == false) {
            terminal.write("Shutdown was never requested. Test FAILED\n");
        }
    }

    var ret = {
      run_test: run_test,
      shutdown: shutdown
    };
    return ret;
};
<commit_msg>Passing RAM parameters to CPU constructor<commit_after>/**
 * Run Tests
 * Copyright (c) 2011 Reginaldo Silva (reginaldo@ubercomp.com)
 * Created: 30/11/11 23:39
 */
"use strict";

lm32.run_tests = function(wait_time, first_test, last_test) {
    if(! wait_time) {
        wait_time = 500;
    }
    var term_element = 'terminal';
    var tests = [
        'test_add.tst.bin',
        'test_addi.tst.bin',
        'test_and.tst.bin',
        'test_andhi.tst.bin',
        'test_andi.tst.bin',
        'test_b.tst.bin',
        'test_be.tst.bin',
        'test_bg.tst.bin',
        'test_bge.tst.bin',
        'test_bgeu.tst.bin',
        'test_bgu.tst.bin',
        'test_bi.tst.bin',
        'test_bne.tst.bin',
        'test_break.tst.bin',
        'test_bret.tst.bin',
        'test_call.tst.bin',
        'test_calli.tst.bin',
        'test_cmpe.tst.bin',
        'test_cmpei.tst.bin',
        'test_cmpg.tst.bin',
        'test_cmpge.tst.bin',
        'test_cmpgei.tst.bin',
        'test_cmpgeu.tst.bin',
        'test_cmpgeui.tst.bin',
        'test_cmpgi.tst.bin',
        'test_cmpgu.tst.bin',
        'test_cmpgui.tst.bin',
        'test_cmpne.tst.bin',
        'test_cmpnei.tst.bin',
        'test_divu.tst.bin',
        'test_eret.tst.bin',
        'test_lb.tst.bin',
        'test_lbu.tst.bin',
        'test_lh.tst.bin',
        'test_lhu.tst.bin',
        'test_lw.tst.bin',
        'test_modu.tst.bin',
        'test_mul.tst.bin',
        'test_muli.tst.bin',
        'test_nor.tst.bin',
        'test_nori.tst.bin',
        'test_or.tst.bin',
        'test_orhi.tst.bin',
        'test_ori.tst.bin',
        'test_ret.tst.bin',
        'test_sb.tst.bin',
        'test_scall.tst.bin',
        'test_sextb.tst.bin',
        'test_sexth.tst.bin',
        'test_sh.tst.bin',
        'test_sl.tst.bin',
        'test_sli.tst.bin',
        'test_sr.tst.bin',
        'test_sri.tst.bin',
        'test_sru.tst.bin',
        'test_srui.tst.bin',
        'test_sub.tst.bin',
        'test_sw.tst.bin',
        'test_xnor.tst.bin',
        'test_xnori.tst.bin',
        'test_xor.tst.bin',
        'test_xori.tst.bin'
    ];
    if(first_test === undefined) {
        first_test = 0;
    }
    if(last_test === undefined) {
        last_test = tests.length - 1;
    }
    console.log("Running tests " + first_test + " through " + last_test);
    var sys = lm32.start_sys(term_element);
    var i = first_test;
    var f = function() {
        sys.shutdown.value = false;
        sys.run_test(tests[i], i, sys.shutdown);
        i++;
        if(i <= last_test) {
            setTimeout(f, wait_time);
        }
    }
    f();
};

lm32.start_sys = function(terminal_div) {
    var RAM_BASE = 0x08000000;
    var RAM_SIZE = 1*1024*1024;
    var EBA_BASE = RAM_BASE;
    var DEBA_BASE = RAM_BASE;

    var TESTDEV_BASE = 0xffff0000;
    var MAX_STEPS = 1000;
    var BOOT_PC = RAM_BASE;

    var mmu = new lm32.MMU();

    var ram = new lm32.RAM(RAM_SIZE, true);

    var cpu_params = {
        mmu: mmu,
        ram: ram,
        ram_base: RAM_BASE,
        ram_size: RAM_SIZE,
        bootstrap_pc: BOOT_PC,
        bootstrap_eba: EBA_BASE,
        bootstrap_deba: DEBA_BASE
    };

    var term = document.getElementById(terminal_div);
    var terminal = (function() {
        return {
          write: function(str) {
              term.textContent = term.textContent + str;
          }
        };
    })();

    terminal.write("LM32 Test Runner\n");

    var shutdown = { value: false };
    function shutdown_f() {
        terminal.write("Shutdown Requested!\n\n");
        shutdown.value = true;
    }

    var testdev_params = {
        mmu: mmu,
        shutdown: shutdown_f,
        terminal: terminal
    };
    var testdev = new lm32.TestDev(testdev_params);
    var DummyTimer = function() {
        this.on_tick = function() {};
    };
    var timer = new DummyTimer();

    mmu.add_memory(RAM_BASE, RAM_SIZE, ram.get_mmio_handlers());
    mmu.add_memory(TESTDEV_BASE, testdev.iomem_size, testdev.get_mmio_handlers());

    function run_test(test_name, idx, shutdown) {
        var cpu = new lm32.Lm32Cpu(cpu_params);
        cpu.set_timers([timer]);
        // testdev.reset();
        var str = "\nRunning Test " + test_name + " (" + idx + ")\n";
        terminal.write(str);
        console.log(str);
        mmu.log = false;
        mmu.load_binary("../test/" + test_name, BOOT_PC);
        mmu.log = true;
        var steps = 0;
        while(shutdown.value == false && steps < MAX_STEPS) {
            cpu.step(1);
            steps++;
        }
        if(shutdown.value == false) {
            terminal.write("Shutdown was never requested. Test FAILED\n");
        }
    }

    var ret = {
      run_test: run_test,
      shutdown: shutdown
    };
    return ret;
};
<|endoftext|>