<commit_before>'use strict';

(function() {

    function ready(fn) {
        if (document.readyState != 'loading') {
            fn();
        }
        else {
            document.addEventListener('DOMContentLoaded', fn);
        }
    }

//-----------------------------------------------------------------------------

    /**
     * Streamer Object
     *
     * Container for a streamer data to be dislayed
     *
     * @param {string} Username [GET /channels/:channel/] => display_name
     * @param {string} Current user activity on channel - [GET /channels/:channel/] => status
     * @param {string} Online/offline flag based on [GET /streams/:channel/] => stream
     * @param {string} Channel logo url - [GET /channels/:channel/] => logo
     */
     var Streamer = function(name, activity, status, icon) {
            this.name = name;
            this.activity = activity;
            this.icon = icon;
            this.status = status;
        };

//-----------------------------------------------------------------------------

    // Twitch.tv API interface

    var ApiInterface = function(app) {
        this.app = app;
        this.connectionErrorMessage = "Can't connect to Twitch.tv, please try again later.";
        this.apiErrorMessage = 'Twitch.tv API error occured';
    };

    ApiInterface.prototype.queryApi = function(uri, success) {
        // build and sent async get request to api
        // uri - API endpoint
        // success - callback functions for request

        var request = new XMLHttpRequest();

        request.onreadystatechange = function() {
            if (request.readyState === 4) {
                if (request.status >= 200 || request.status < 400) {
                    success(JSON.parse(request.responseText));
                }
                else {
                    this.app.view.errorDiv.innerHTML = this.connectionErrorMessage;
                }
            }
        }.bind(this);

        request.open('GET', 'https://api.twitch.tv/kraken/' + uri, true);
        request.onerror = function(e) {
            this.app.view.errorDiv.innerHTML = this.apiErrorMessage;
        }.bind(this);

        request.setRequestHeader('Accept', 'application/vnd.twitchtv.v3+json');
        request.send();
    };

    ApiInterface.prototype.getChannelDetails = function(channel) {
        this.queryApi('channels/' + channel,

            function(response) {
                var channelResponse = response;

                this.queryApi('streams/' + channel, function(response) {
                    var streamerStatus = response.stream == null ? 'offline' : 'online';
                    var channelData = new Streamer(channelResponse.name, channelResponse.status, streamerStatus, channelResponse.logo);
                    this.app.scope.channelsData.push(channelData);
                    this.app.view.renderList();
                }.bind(this));
        }.bind(this));
    };

//-----------------------------------------------------------------------------
    // View Object

    var View = function(scope) {
        this.scope = scope;
        this.list = document.getElementById('streamers');
        this.errorDiv = document.getElementById('error');
    };

    View.prototype.renderList = function() {
        this.list.innerHTML = '';

        this.scope.channelsData.forEach(function(element) {
            var li = '
';
            li += '

';
            li += '
' + element.name + '
';
            li += '
' + element.activity + '
' + '
';
            this.list.insertAdjacentHTML('beforeend', li);
        }.bind(this));
    };

//-----------------------------------------------------------------------------
    // Main App

    var App = function() {

        this.scope = {};

        this.view = new View(this.scope);
        this.api = new ApiInterface(this);

        this.scope.channelsNames = ['ESL_SC2', 'freecodecamp', 'storbeck', 'OgamingSC2'];

        this.scope.channelsData = [];
    };

    App.prototype.getChannelsData = function(channelsNames) {
        channelsNames.forEach(function(channel) {
            this.api.getChannelDetails(channel);
        }.bind(this));
    };

    App.prototype.start = function() {
        this.getChannelsData(this.scope.channelsNames);
    };

    var app = new App;
    ready(app.start.bind(app));

})();<commit_msg>Function renderList is called only once every channel data is available<commit_after>'use strict';

(function() {

    function ready(fn) {
        if (document.readyState != 'loading') {
            fn();
        }
        else {
            document.addEventListener('DOMContentLoaded', fn);
        }
    }

    //-----------------------------------------------------------------------------

    /**
     * Streamer Object
     *
     * Container for a streamer data to be dislayed
     *
     * @param {string} Username [GET /channels/:channel/] => display_name
     * @param {string} Current user activity on channel - [GET /channels/:channel/] => status
     * @param {string} Online/offline flag based on [GET /streams/:channel/] => stream
     * @param {string} Channel logo url - [GET /channels/:channel/] => logo
     */
    var Streamer = function(name, activity, status, icon) {
        this.name = name;
        this.activity = activity;
        this.icon = icon;
        this.status = status;
    };

    //-----------------------------------------------------------------------------

    // Twitch.tv API interface

    var ApiInterface = function(app) {
        this.app = app;
        this.connectionErrorMessage = "Can't connect to Twitch.tv, please try again later.";
        this.apiErrorMessage = 'Twitch.tv API error occured';
    };

    ApiInterface.prototype.queryApi = function(uri, success) {
        // build and sent async get request to api
        // uri - API endpoint
        // success - callback functions for request

        var request = new XMLHttpRequest();

        request.onreadystatechange = function() {
            if (request.readyState === 4) {
                if (request.status >= 200 || request.status < 400) {
                    success(JSON.parse(request.responseText));
                }
                else {
                    this.app.view.errorDiv.innerHTML = this.connectionErrorMessage;
                }
            }
        }.bind(this);

        request.open('GET', 'https://api.twitch.tv/kraken/' + uri, true);
        request.onerror = function(e) {
            this.app.view.errorDiv.innerHTML = this.apiErrorMessage;
        }.bind(this);

        request.setRequestHeader('Accept', 'application/vnd.twitchtv.v3+json');
        request.send();
    };

    ApiInterface.prototype.getChannelDetails = function(channel, dataItemsCount) {
        this.queryApi('channels/' + channel,

            function(response) {
                var channelResponse = response;

                this.queryApi('streams/' + channel, function(response) {
                    var streamerStatus = response.stream == null ? 'offline' : 'online';
                    var channelData = new Streamer(channelResponse.name, channelResponse.status, streamerStatus, channelResponse.logo);
                    this.app.scope.channelsData.push(channelData);
                    if (this.app.scope.channelsData.length === dataItemsCount) {
                        this.app.view.renderList();
                    }
                }.bind(this));
            }.bind(this));
    };

    //-----------------------------------------------------------------------------
    // View Object

    var View = function(scope) {
        this.scope = scope;
        this.list = document.getElementById('streamers');
        this.errorDiv = document.getElementById('error');
    };

    View.prototype.renderList = function() {
        this.list.innerHTML = '';

        this.scope.channelsData.forEach(function(element) {
            var li = '
';
            li += '

';
            li += '
' + element.name + '
';
            li += '
' + element.activity + '
' + '
';
            this.list.insertAdjacentHTML('beforeend', li);
        }.bind(this));
    };

    //-----------------------------------------------------------------------------
    // Main App

    var App = function() {

        this.scope = {};

        this.view = new View(this.scope);
        this.api = new ApiInterface(this);

        this.scope.channelsNames = ['ESL_SC2', 'freecodecamp', 'storbeck', 'OgamingSC2'];

        this.scope.channelsData = [];
    };

    App.prototype.getChannelsData = function(channelsNames, callback) {
        var App = this;

        channelsNames.forEach(function(channel, index, arr) {
            App.api.queryApi('channels/' + channel, function(response) {
                var channelResponse = response;
                App.api.queryApi('streams/' + channel, function(response) {
                    var streamerStatus = response.stream == null ? 'offline' : 'online';
                    var channelData = new Streamer(channelResponse.name, channelResponse.status, streamerStatus, channelResponse.logo);
                    App.scope.channelsData.push(channelData);
                    if (App.scope.channelsData.length === arr.length) {
                        callback();
                    }
                });
            });
        });
    };

    App.prototype.start = function() {
        this.getChannelsData(this.scope.channelsNames, this.view.renderList.bind(this.view));
    };

    var app = new App;
    ready(app.start.bind(app));

})();<|endoftext|>


<commit_before>//  containers
var visnetwork = document.getElementById('visnetwork');
var visconfig = document.getElementById('visconfig');

function toggleConfiguration() {
    if (visnetwork.style.width !== '70%') {
        visnetwork.style.width = '70%';
        return;
    }
    visnetwork.style.width = '100%';
}

// options
var visoptions = {
    nodes: {
        shape: 'dot',
        font: {
            size: 14,
            //color: 'white',
            strokeColor: 'rgba(250,250,250,1)',
            strokeWidth: 2
        },
        color: {
            border: '#080808',
            background: 'gray',
            hover: { border: '#E5CC67', background: 'lightyellow' },
            highlight: { border: '#5DB9BB', background: 'lightblue' },
        },
        shadow: {size: 4, x: -3, y: -3, color: 'rgba(0,0,0,0.4)'},
    },
    edges: {
        color: {
            color: '#444',
            hover: '#E5D594',
            highlight: '#79B9BB'
        }
    },
    physics: {
        //stabilization: false,
        maxVelocity: 30,
        barnesHut: {
            avoidOverlap: 0.1
        }
    },
    interaction: {
        hover: true
    },
    configure: {
        container: visconfig,
    },
    groups: {
        topLevels: {
            shape: 'circularImage',
            size: 14,
            color: { background: 'rgba(128,128,128,0.75)', border: '#080808' },
        },
        folders: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 20,
                color: 'darkgray',
                code: '\uf07b'
            },
            /*shape: 'ellipse',
            color: {background: 'rgba(128,128,128,1)'},
            font: {
                color: 'white',
                //strokeColor: '#f8f8f8',
                strokeWidth: 3
            },*/
            mass: 2
        },
        files: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 15,
                color: 'dimgray',
                code: '\uf016'
            },
        },
        sources: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 15,
                color: 'lightskyblue',
                code: '\uf15c'
            },
        },
        packages: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 30,
                color: '#78CCFF',
                code: '\uf1b2'
            },
            mass: 3
        },
        programs: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 30,
                color: '#76C476',
                code: '\uf109'
            },
            mass: 3
        },
        objects: {
            shape: 'box',
            color: {
                background: 'aliceblue'
            },
            font: {
                color: '#111',
                multi: true,
                strokeWidth: 0,
                mono: {
                    color: '#333',
                    size: 10,
                    vadjust: 0
                }
            }
        },
    }
};

// network
var nodes = new vis.DataSet([ ]);
var edges = new vis.DataSet([ ]);
nodes.on('*', function (event, properties, senderId) {
  console.info('nodes event:', event, 'properties:', properties, 'senderId:', senderId);
});

var visdata = { nodes: nodes, edges: edges };
var network = new vis.Network(visnetwork, visdata, visoptions);

// cursor
var viscanvas = visnetwork.getElementsByTagName("canvas")[0];
function changeCursor(c){
    viscanvas.style.cursor = c;
}
network.on('hoverNode', function(){
    changeCursor('pointer');
});
network.on('blurNode', function(){
    changeCursor('default');
});

document.addEventListener('keydown', function(event) {
    console.debug("keydown", event);
    if (event.code === 'Delete') {
        var sel = network.getSelectedNodes();
        if (sel.length>0) {
            var id = sel[0];
            nodes.update({id: id, open: false});
            removeChildren(id);
            network.unselectAll();
        }
    }
}, false);

// GOPATH node
var nodeGopath = {
    id: '$GOPATH',
    label: '$GOPATH',
    title: 'explore $GOPATH',
    shape: 'image',
    image: './static/img/gopher.png',
    color: {
        background: '#888',
        border: '#111'
    },
    size: 22,
    mass: 5,
    dir: '.'
};
nodes.add(nodeGopath);

var hideChildren = function(nodeId, hide) {
    console.debug("hideChildren", nodeId, hide);
    var oldNode = nodes.get(nodeId);
    var i = 0;
    var parents = {};

    var upedges = [];
    var seledges = network.getConnectedEdges(nodeId);
    for (i=0; i<seledges.length; i++) {
        var seledge = edges.get(seledges[i]);
        if (seledge.from !== nodeId) {
            parents[seledge.from] = true;
            continue;
        }
        var e = { id: seledges[i] };
        if (hide) {
            e.color = {opacity: 0.5};
        }
        upedges.push(e);
    }

    var theNode = {
        id: nodeId,
        //font: {color: 'rgba(255,255,255,1)', strokeColor: 'rgba(0,0,0,1)'},
        //icon: {color: 'rgba(200,200,200,1)'}
    };
    if (hide) {
        //theNode.font = {color: 'rgba(200,200,200,0.2)', strokeColor: 'rgba(0,0,0,0.1)'};
        //theNode.icon = {color: 'rgba(128,128,128,0.5)'};
    }

    var upnodes = [theNode];
    var selnodes = network.getConnectedNodes(nodeId);
    for (i=0; i<selnodes.length; i++) {
        var selnode = nodes.get(selnodes[i]);
        if (selnode.id === nodeId || parents[selnode.id] === true) {
            continue;
        }
        var n = {
            id: selnodes[i],
            //font: {color: 'rgba(255,255,255,1)', strokeColor: 'rgba(0,0,0,1)'},
            //icon: {color: 'rgba(200,200,200,1)'},
            //color: {background: 'rgba(128,128,128,1)', border: 'rgba(128,128,128,1)'},
        };
        if (hide) {
            /*n.oldFont = {
                color: selnode.font.color,
                strokeColor: selnode.font.strokeColor,
            };*/
            //n.font = {color: 'rgba(200,200,200,0.5)', strokeColor: 'rgba(0,0,0,0.1)'};
            //n.icon = {color: 'rgba(128,128,128,0.5)'};
            //n.color = {background: 'rgba(128,128,128,0.25)', border: 'rgba(128,128,128,0.5)'};
        }else{
            /*if (selnode.oldFont) {
                n.font = selnode.oldFont;
                n.oldFont = undefined;
            //}else{
            //    n.font = {};
        }*/
        }
        upnodes.push(n);
    }

    console.log("upnodes", upnodes);

    nodes.update(upnodes);
    edges.update(upedges);
};

var removeChildren = function(nodeId) {
    console.debug("removeChildren", nodeId);
    var oldNode = nodes.get(nodeId);
    var i = 0;
    var parents = {};

    var upedges = [];
    var seledges = network.getConnectedEdges(nodeId);
    for (i=0; i<seledges.length; i++) {
        var seledge = edges.get(seledges[i]);
        if (seledge.from !== nodeId) {
            parents[seledge.from] = true;
            continue;
        }
        upedges.push(seledges[i]);
    }

    var upnodes = [];
    var selnodes = network.getConnectedNodes(nodeId);
    for (i=0; i<selnodes.length; i++) {
        var selnode = nodes.get(selnodes[i]);
        if (selnode.id === nodeId || parents[selnode.id] === true) {
            continue;
        }
        if (selnode.open) {
            removeChildren(selnode.id);
        }
        upnodes.push(selnodes[i]);
    }

    console.log("upnodes", upnodes);

    nodes.remove(upnodes);
    edges.remove(upedges);
};

network.on('selectNode', function(data){
    var node = nodes.get(data.nodes[0]);
    console.log("selectNode:", node.id, data);
    if (node.dir) {
        updatePath(node);
    }
});

network.on('deselectNode', function(data){
    var node = nodes.get(data.previousSelection.nodes[0]);
    console.log("deselectNode:", node.id, data);
    clearPath(node);
});

network.on('dragEnd', function(data){
    console.log("dragEnd:", data);
    if (data && data.nodes && data.nodes) {

    }
});

var clearPath = function(node) {
    if (!node && !node.id) {
        console.log("no node", node);
        return;
    }
    console.debug("clearPath:", node);
    hideChildren(node.id, true);
    //nodes.update([{id: node.id, open: false}]);
};

var updatePath = function(node) {
    if (!node && !node.id) {
        console.log("no node", node);
        return;
    }

    var p = '?';
    if (node.dir) {
        p += 'dir='+node.dir;
    }

    hideChildren(node.id, false);
    network.fit({
        nodes: network.getConnectedNodes(node.id),
        animation: {
            duration: 500,
            easingFunction: 'easeOutQuint'
        }
    });

    var opening = !node.open;
    console.debug("updatePath:", opening, node);
    if (!opening) {
        console.log("not opening", node);
        return;
    }

    var nodePos = network.getPositions(node.id);

    httpGetJson("/gopath"+p, function(data){
        console.log("gopath success:", data);
        var files = data;

        var nodeList = [];
        var edgeList = [];
        for (var i=0; i<files.length; i++) {
            var file = files[i];
            var n = {
                id: file.Id,
                label: file.Label,
                title: "<b>"+file.Loc+"</b>",
                value: file.Value,
                dir: file.Loc,
                hidden: false,
                font: {
                    size: 12,
                    //color: '#D8D8D8',
                    //strokeColor: '#080808',
                },
                x: nodePos.x,
                y: nodePos.y
            };
            if (file.Type === "topLevel") {
                n.group = 'topLevels';
                n.image = 'http://' + file.Label + '/favicon.ico';
                //n.brokenImage = '';
            }else if (file.Type === "folder") {
                n.group = 'folders';
            }else if (file.Type === "source"){
                n.group = 'sources';
            }else if (file.Type === "package"){
                n.group = 'packages';
            }else if (file.Type === "program"){
                n.group = 'programs';
            }else if (file.Type === "object"){
                n.group = 'objects';
            }else{
                n.group = 'files';
            }
            nodeList.push(n);

            var edgeId = node.id + '->' + file.Id;
            var e = {
                id: edgeId,
                from: node.id, to: file.Id,
                hidden: false
            };
            edgeList.push(e);
        }
        var par = {
            id: node.id,
            open: opening,
        };
        nodeList.push(par);
        /*if (node.imageOpen && opening) {
            console.log('imageOpen', node.imageOpen);
            n.image = node.imageOpen;
        }*/
        nodes.update(nodeList);
        edges.update(edgeList);

        network.selectNodes([node.id]);
    });
};

var httpGetJson = function(url, successCb) {
    var r = new XMLHttpRequest();
    r.responseType = "json";
    r.open("GET", url, true);
    r.onreadystatechange = function () {
        if (r.readyState != 4 || r.status != 200) return;
        successCb(r.response);
    };
    r.send();
};

//updatePath(nodeGopath);
<commit_msg>Adjust label style<commit_after>//  containers
var visnetwork = document.getElementById('visnetwork');
var visconfig = document.getElementById('visconfig');

function toggleConfiguration() {
    if (visnetwork.style.width !== '70%') {
        visnetwork.style.width = '70%';
        return;
    }
    visnetwork.style.width = '100%';
}

// options
var visoptions = {
    nodes: {
        shape: 'dot',
        font: {
            size: 14,
            color: 'rgba(0,0,0,1)',
            strokeColor: 'rgba(250,250,250,1)',
            strokeWidth: 3
        },
        color: {
            border: '#080808',
            background: 'gray',
            hover: { border: '#E5CC67', background: 'lightyellow' },
            highlight: { border: '#5DB9BB', background: 'lightblue' },
        },
        shadow: {size: 4, x: -3, y: -3, color: 'rgba(0,0,0,0.4)'},
    },
    edges: {
        color: {
            color: '#444',
            hover: '#E5D594',
            highlight: '#79B9BB'
        }
    },
    physics: {
        //stabilization: false,
        maxVelocity: 30,
        barnesHut: {
            avoidOverlap: 0.1
        }
    },
    interaction: {
        hover: true
    },
    configure: {
        container: visconfig,
    },
    groups: {
        topLevels: {
            shape: 'circularImage',
            size: 14,
            color: { background: 'rgba(128,128,128,0.75)', border: '#080808' },
        },
        folders: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 20,
                color: 'darkgray',
                code: '\uf07b'
            },
            /*shape: 'ellipse',
            color: {background: 'rgba(128,128,128,1)'},
            font: {
                color: 'white',
                //strokeColor: '#f8f8f8',
                strokeWidth: 3
            },*/
            mass: 2
        },
        files: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 15,
                color: 'dimgray',
                code: '\uf016'
            },
        },
        sources: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 15,
                color: 'lightskyblue',
                code: '\uf15c'
            },
        },
        packages: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 30,
                color: '#78CCFF',
                code: '\uf1b2'
            },
            mass: 3
        },
        programs: {
            shape: 'icon',
            icon: {
                face: 'FontAwesome',
                size: 30,
                color: '#76C476',
                code: '\uf109'
            },
            mass: 3
        },
        objects: {
            shape: 'box',
            color: {
                background: 'aliceblue'
            },
            font: {
                color: '#111',
                multi: true,
                strokeWidth: 0,
                mono: {
                    color: '#333',
                    size: 10,
                    vadjust: 0
                }
            }
        },
    }
};

// network
var nodes = new vis.DataSet([ ]);
var edges = new vis.DataSet([ ]);
nodes.on('*', function (event, properties, senderId) {
  console.info('nodes event:', event, 'properties:', properties, 'senderId:', senderId);
});

var visdata = { nodes: nodes, edges: edges };
var network = new vis.Network(visnetwork, visdata, visoptions);

// cursor
var viscanvas = visnetwork.getElementsByTagName("canvas")[0];
function changeCursor(c){
    viscanvas.style.cursor = c;
}
network.on('hoverNode', function(){
    changeCursor('pointer');
});
network.on('blurNode', function(){
    changeCursor('default');
});

document.addEventListener('keydown', function(event) {
    console.debug("keydown", event);
    if (event.code === 'Delete') {
        var sel = network.getSelectedNodes();
        if (sel.length>0) {
            var id = sel[0];
            nodes.update({id: id, open: false});
            removeChildren(id);
            network.unselectAll();
        }
    }
}, false);

// GOPATH node
var nodeGopath = {
    id: '$GOPATH',
    label: '$GOPATH',
    title: 'explore $GOPATH',
    shape: 'image',
    image: './static/img/gopher.png',
    color: {
        background: '#888',
        border: '#111'
    },
    size: 22,
    mass: 5,
    dir: '.'
};
nodes.add(nodeGopath);

var hideChildren = function(nodeId, hide) {
    console.debug("hideChildren", nodeId, hide);
    var oldNode = nodes.get(nodeId);
    var i = 0;
    var parents = {};

    var upedges = [];
    var seledges = network.getConnectedEdges(nodeId);
    for (i=0; i<seledges.length; i++) {
        var seledge = edges.get(seledges[i]);
        if (seledge.from !== nodeId) {
            parents[seledge.from] = true;
            continue;
        }
        var e = { id: seledges[i] };
        if (hide) {
            e.color = {opacity: 0.5};
        }
        upedges.push(e);
    }

    var theNode = {
        id: nodeId,
        //font: {color: 'rgba(255,255,255,1)', strokeColor: 'rgba(0,0,0,1)'},
        //icon: {color: 'rgba(200,200,200,1)'}
    };
    if (hide) {
        //theNode.font = {color: 'rgba(200,200,200,0.2)', strokeColor: 'rgba(0,0,0,0.1)'};
        //theNode.icon = {color: 'rgba(128,128,128,0.5)'};
    }

    var upnodes = [theNode];
    var selnodes = network.getConnectedNodes(nodeId);
    for (i=0; i<selnodes.length; i++) {
        var selnode = nodes.get(selnodes[i]);
        if (selnode.id === nodeId || parents[selnode.id] === true) {
            continue;
        }
        var n = {
            id: selnodes[i],
            //font: {color: 'rgba(255,255,255,1)', strokeColor: 'rgba(0,0,0,1)'},
            //icon: {color: 'rgba(200,200,200,1)'},
            //color: {background: 'rgba(128,128,128,1)', border: 'rgba(128,128,128,1)'},
        };
        if (hide) {
            /*n.oldFont = {
                color: selnode.font.color,
                strokeColor: selnode.font.strokeColor,
            };*/
            //n.font = {color: 'rgba(200,200,200,0.5)', strokeColor: 'rgba(0,0,0,0.1)'};
            //n.icon = {color: 'rgba(128,128,128,0.5)'};
            //n.color = {background: 'rgba(128,128,128,0.25)', border: 'rgba(128,128,128,0.5)'};
        }else{
            /*if (selnode.oldFont) {
                n.font = selnode.oldFont;
                n.oldFont = undefined;
            //}else{
            //    n.font = {};
        }*/
        }
        upnodes.push(n);
    }

    console.log("upnodes", upnodes);

    nodes.update(upnodes);
    edges.update(upedges);
};

var removeChildren = function(nodeId) {
    console.debug("removeChildren", nodeId);
    var oldNode = nodes.get(nodeId);
    var i = 0;
    var parents = {};

    var upedges = [];
    var seledges = network.getConnectedEdges(nodeId);
    for (i=0; i<seledges.length; i++) {
        var seledge = edges.get(seledges[i]);
        if (seledge.from !== nodeId) {
            parents[seledge.from] = true;
            continue;
        }
        upedges.push(seledges[i]);
    }

    var upnodes = [];
    var selnodes = network.getConnectedNodes(nodeId);
    for (i=0; i<selnodes.length; i++) {
        var selnode = nodes.get(selnodes[i]);
        if (selnode.id === nodeId || parents[selnode.id] === true) {
            continue;
        }
        if (selnode.open) {
            removeChildren(selnode.id);
        }
        upnodes.push(selnodes[i]);
    }

    console.log("upnodes", upnodes);

    nodes.remove(upnodes);
    edges.remove(upedges);
};

network.on('selectNode', function(data){
    var node = nodes.get(data.nodes[0]);
    console.log("selectNode:", node.id, data);
    if (node.dir) {
        updatePath(node);
    }
});

network.on('deselectNode', function(data){
    var node = nodes.get(data.previousSelection.nodes[0]);
    console.log("deselectNode:", node.id, data);
    clearPath(node);
});

network.on('dragEnd', function(data){
    console.log("dragEnd:", data);
    if (data && data.nodes && data.nodes) {

    }
});

var clearPath = function(node) {
    if (!node && !node.id) {
        console.log("no node", node);
        return;
    }
    console.debug("clearPath:", node);
    hideChildren(node.id, true);
    //nodes.update([{id: node.id, open: false}]);
};

var updatePath = function(node) {
    if (!node && !node.id) {
        console.log("no node", node);
        return;
    }

    var p = '?';
    if (node.dir) {
        p += 'dir='+node.dir;
    }

    hideChildren(node.id, false);
    network.fit({
        nodes: network.getConnectedNodes(node.id),
        animation: {
            duration: 500,
            easingFunction: 'easeOutQuint'
        }
    });

    var opening = !node.open;
    console.debug("updatePath:", opening, node);
    if (!opening) {
        console.log("not opening", node);
        return;
    }

    var nodePos = network.getPositions(node.id);

    httpGetJson("/gopath"+p, function(data){
        console.log("gopath success:", data);
        var files = data;

        var nodeList = [];
        var edgeList = [];
        for (var i=0; i<files.length; i++) {
            var file = files[i];
            var n = {
                id: file.Id,
                label: file.Label,
                title: "<b>"+file.Loc+"</b>",
                value: file.Value,
                dir: file.Loc,
                hidden: false,
                font: {
                    size: 12,
                    //color: '#D8D8D8',
                    //strokeColor: '#080808',
                },
                x: nodePos.x,
                y: nodePos.y
            };
            if (file.Type === "topLevel") {
                n.group = 'topLevels';
                n.image = 'http://' + file.Label + '/favicon.ico';
                //n.brokenImage = '';
            }else if (file.Type === "folder") {
                n.group = 'folders';
            }else if (file.Type === "source"){
                n.group = 'sources';
            }else if (file.Type === "package"){
                n.group = 'packages';
            }else if (file.Type === "program"){
                n.group = 'programs';
            }else if (file.Type === "object"){
                n.group = 'objects';
            }else{
                n.group = 'files';
            }
            nodeList.push(n);

            var edgeId = node.id + '->' + file.Id;
            var e = {
                id: edgeId,
                from: node.id, to: file.Id,
                hidden: false
            };
            edgeList.push(e);
        }
        var par = {
            id: node.id,
            open: opening,
        };
        nodeList.push(par);
        /*if (node.imageOpen && opening) {
            console.log('imageOpen', node.imageOpen);
            n.image = node.imageOpen;
        }*/
        nodes.update(nodeList);
        edges.update(edgeList);

        network.selectNodes([node.id]);
    });
};

var httpGetJson = function(url, successCb) {
    var r = new XMLHttpRequest();
    r.responseType = "json";
    r.open("GET", url, true);
    r.onreadystatechange = function () {
        if (r.readyState != 4 || r.status != 200) return;
        successCb(r.response);
    };
    r.send();
};

//updatePath(nodeGopath);
<|endoftext|>


<commit_before>var pubcal = angular.module('pubcal', ['firebase']);

function PubCalController($scope, angularFire) {
  $scope.events = [];
  var ref = new Firebase(firebase_url);
  angularFire(ref, $scope, "events");

  var monthNames = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December",
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
  ];

  var monthAbrevs = [
    "Jan", "Feb", "Mar", "Apr", "May", "June",
    "July", "Aug", "Sept", "Oct", "Nov", "Dec",
  ];

  var tierNames = ["error", "success", "info", "", "error"];

  $scope.updateFilter = function() {
    console.log("called with " + $scope.searchstring);
    $scope.hide = [];
    if($scope.searchstring.length > 0) {
      for(e in $scope.events) {
	var cur = $scope.events[e];
	console.log(cur.name + " " + cur.short_name + " " + cur.description +
	  " " + cur.categories);
	if((cur.name + " " + cur.short_name + " " + cur.description +
	  " " + cur.categories).toLowerCase().indexOf($scope.searchstring.toLowerCase()) == -1) {
	  $scope.hide.push(cur);
	}
      }
    }
  }

  $scope.edit = {
    start: {month:"January", day: 0},
    end: {month:"January", day: 0},
    replaces: -1,
    short_name: "",
    name: "",
    description: "",
    categories: "",
    tier:1
  };

  $scope.updateView = function() {
    var months = $("#months");
    var table = $("#maintable");

    months.empty();
    table.empty();

    for(m in monthNames) {
      months.append("
 11 ? "next" : "") + "' class='nomarg alert alert-" + ((m % 2) ? "success" : "info") + "'>" + monthNames[m] + "
");
    }

    events = _.sortBy($scope.events, function(e) { return e.start.month * 100 + e.start.day; });

    var columns = [];
    var datelist = _.map(monthNames, function(v, k) { return (1+k) * 100; });
    datelist = _.union(datelist, _.map(events, function(v) { if(_.contains($scope.hide, v)) return 0; else return v.start.month * 100 + v.start.day; }));
    datelist = _.union(datelist, _.map(events, function(v) { if(_.contains($scope.hide, v)) return 0; else return ((v.end.month < v.start.month ? 12 : 0) + v.end.month) * 100 + v.end.day; }));
    datelist.sort(function(a,b) { return a-b; });

    for(e in events) {
      if(_.contains($scope.hide, events[e]))
	continue;

      var cur = events[e];
      var found = false;

      for(c in columns) {
	var last = _.last(columns[c]);
	if((((last.start.month > last.end.month ? 12 : 0) + last.end.month) * 100 + last.end.day) < (cur.start.month * 100 + cur.start.day)) {
	  columns[c].push(cur);
	  found = true;
	  break;
	}
      }

      if(!found) {
	columns.push([cur]);
      }
    }

    for(d in datelist) {
      var curday = datelist[d] % 100;
      var curmonth = (datelist[d] / 100) | 0;
      if(curday != 0) {
	$("#" + monthNames[curmonth-1] + (curmonth > 11 ? "next" : "")).append("
   " + curday);
      }
    }

    table.append("

");
    var tablerow = $("#mainrow");
    var text_height = 20;
    for(c in columns) {
      var column = columns[c];
      tablerow.append("	");
      var tablecol = $("#column" + c);
      var last_end = 0;
      for(e in column) {
	var cur = column[e];
	var start_height = text_height * _.indexOf(datelist, cur.start.month * 100 + cur.start.day) + cur.start.month * 2 - 1 - (e * 2 + 1);
	var end_height = text_height * (1 + _.indexOf(datelist, ((cur.end.month < cur.start.month ? 12 : 0) + cur.end.month) * 100 + cur.end.day)) + ((cur.end.month < cur.start.month ? 12 : 0) + cur.end.month) * 2 - 1;
	tablecol.append("
" + cur.short_name + "
" + (cur.start.day > 0 ? monthAbrevs[cur.start.month-1] + " " + cur.start.day : "") + "
");
	$("#event" + c + "x" + e).popover({title:cur.name + "(" + cur.short_name + ")", html:true, placement:'bottom',
	  content:
	    "Submission
" + monthNames[cur.start.month-1] + " " + (cur.start.day > 0 ? cur.start.day : "") + "
" +
	    "Conference
" + monthNames[cur.end.month-1] + " " + (cur.end.day > 0 ? cur.end.day : "") + "
" +
	    "Description
" + cur.description + "
" +
	    "Categories
" + cur.categories + "
" +
	    "Tier
" + cur.tier
	  , trigger:'hover'});
	$("#event" + c + "x" + e).click((function(cur) { return function() {
          $scope.edit = jQuery.extend(true, {}, cur);
	  $scope.edit.start.month = monthNames[cur.start.month-1];
	  $scope.edit.end.month = monthNames[cur.end.month-1];
	  $scope.edit.replaces = cur;
	  $("#editmodal").on('shown', (function(cur) { return function() {
	    $scope.$apply();
	  };})(cur));
	};})(cur));
	last_end = end_height;
      }
    }
  }

  $scope.getEdit = function() {
    return $scope.edit;
  }

  $scope.createNew = function() {
    $scope.edit = {
      start: {month:"January", day: 0},
      end: {month:"January", day: 0},
      replaces: -1,
      short_name: "",
      name: "",
      description: "",
      categories: "",
      tier:1
    };
  }

  $scope.createOrUpdate = function() {
    var cur = $scope.edit.replaces;
    $scope.edit.replaces = -1;
    if(cur == -1) {
      var newpub = jQuery.extend(true, {}, $scope.edit);
      newpub.start.month = _.indexOf(monthNames, $scope.edit.start.month)+1;
      newpub.end.month = _.indexOf(monthNames, $scope.edit.end.month)+1;
      newpub.start.day = parseInt($scope.edit.start.day);
      newpub.end.day = parseInt($scope.edit.end.day);
      $scope.events.push(newpub);
    } else {
      var index = _.indexOf($scope.events, cur);
      $scope.events[index] = jQuery.extend(true, {}, $scope.edit);
      cur = $scope.events[index];
      cur.start.month = _.indexOf(monthNames, $scope.edit.start.month)+1;
      cur.end.month = _.indexOf(monthNames, $scope.edit.end.month)+1;
      cur.start.day = parseInt($scope.edit.start.day);
      cur.end.day = parseInt($scope.edit.end.day);
    }
  }

  $scope.removeCurrent = function() {
    var cur = $scope.edit.replaces;
    $scope.edit.replaces = -1;
    if(cur != -1) {
      $scope.evenets = $scope.events.splice(_.indexOf(events, cur),1);
    }
  }
}
<commit_msg>searchable months by name too<commit_after>var pubcal = angular.module('pubcal', ['firebase']);

function PubCalController($scope, angularFire) {
  $scope.events = [];
  var ref = new Firebase(firebase_url);
  angularFire(ref, $scope, "events");

  var monthNames = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December",
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
  ];

  var monthAbrevs = [
    "Jan", "Feb", "Mar", "Apr", "May", "June",
    "July", "Aug", "Sept", "Oct", "Nov", "Dec",
  ];

  var tierNames = ["error", "success", "info", "", "error"];

  $scope.updateFilter = function() {
    $scope.hide = [];
    if($scope.searchstring.length > 0) {
      for(e in $scope.events) {
	var cur = $scope.events[e];
	if((cur.name + " " + cur.short_name + " " + cur.description +
	  " " + cur.categories + monthNames[cur.start.month-1] + monthNames[cur.end.month-1])
	  .toLowerCase().indexOf($scope.searchstring.toLowerCase()) == -1) {

	    $scope.hide.push(cur);
	}
      }
    }
  }

  $scope.edit = {
    start: {month:"January", day: 0},
    end: {month:"January", day: 0},
    replaces: -1,
    short_name: "",
    name: "",
    description: "",
    categories: "",
    tier:1
  };

  $scope.updateView = function() {
    var months = $("#months");
    var table = $("#maintable");

    months.empty();
    table.empty();

    for(m in monthNames) {
      months.append("
 11 ? "next" : "") + "' class='nomarg alert alert-" + ((m % 2) ? "success" : "info") + "'>" + monthNames[m] + "
");
    }

    events = _.sortBy($scope.events, function(e) { return e.start.month * 100 + e.start.day; });

    var columns = [];
    var datelist = _.map(monthNames, function(v, k) { return (1+k) * 100; });
    datelist = _.union(datelist, _.map(events, function(v) { if(_.contains($scope.hide, v)) return 0; else return v.start.month * 100 + v.start.day; }));
    datelist = _.union(datelist, _.map(events, function(v) { if(_.contains($scope.hide, v)) return 0; else return ((v.end.month < v.start.month ? 12 : 0) + v.end.month) * 100 + v.end.day; }));
    datelist.sort(function(a,b) { return a-b; });

    for(e in events) {
      if(_.contains($scope.hide, events[e]))
	continue;

      var cur = events[e];
      var found = false;

      for(c in columns) {
	var last = _.last(columns[c]);
	if((((last.start.month > last.end.month ? 12 : 0) + last.end.month) * 100 + last.end.day) < (cur.start.month * 100 + cur.start.day)) {
	  columns[c].push(cur);
	  found = true;
	  break;
	}
      }

      if(!found) {
	columns.push([cur]);
      }
    }

    for(d in datelist) {
      var curday = datelist[d] % 100;
      var curmonth = (datelist[d] / 100) | 0;
      if(curday != 0) {
	$("#" + monthNames[curmonth-1] + (curmonth > 11 ? "next" : "")).append("
   " + curday);
      }
    }

    table.append("

");
    var tablerow = $("#mainrow");
    var text_height = 20;
    for(c in columns) {
      var column = columns[c];
      tablerow.append("	");
      var tablecol = $("#column" + c);
      var last_end = 0;
      for(e in column) {
	var cur = column[e];
	var start_height = text_height * _.indexOf(datelist, cur.start.month * 100 + cur.start.day) + cur.start.month * 2 - 1 - (e * 2 + 1);
	var end_height = text_height * (1 + _.indexOf(datelist, ((cur.end.month < cur.start.month ? 12 : 0) + cur.end.month) * 100 + cur.end.day)) + ((cur.end.month < cur.start.month ? 12 : 0) + cur.end.month) * 2 - 1;
	tablecol.append("
" + cur.short_name + "
" + (cur.start.day > 0 ? monthAbrevs[cur.start.month-1] + " " + cur.start.day : "") + "
");
	$("#event" + c + "x" + e).popover({title:cur.name + "(" + cur.short_name + ")", html:true, placement:'bottom',
	  content:
	    "Submission
" + monthNames[cur.start.month-1] + " " + (cur.start.day > 0 ? cur.start.day : "") + "
" +
	    "Conference
" + monthNames[cur.end.month-1] + " " + (cur.end.day > 0 ? cur.end.day : "") + "
" +
	    "Description
" + cur.description + "
" +
	    "Categories
" + cur.categories + "
" +
	    "Tier
" + cur.tier
	  , trigger:'hover'});
	$("#event" + c + "x" + e).click((function(cur) { return function() {
          $scope.edit = jQuery.extend(true, {}, cur);
	  $scope.edit.start.month = monthNames[cur.start.month-1];
	  $scope.edit.end.month = monthNames[cur.end.month-1];
	  $scope.edit.replaces = cur;
	  $("#editmodal").on('shown', (function(cur) { return function() {
	    $scope.$apply();
	  };})(cur));
	};})(cur));
	last_end = end_height;
      }
    }
  }

  $scope.getEdit = function() {
    return $scope.edit;
  }

  $scope.createNew = function() {
    $scope.edit = {
      start: {month:"January", day: 0},
      end: {month:"January", day: 0},
      replaces: -1,
      short_name: "",
      name: "",
      description: "",
      categories: "",
      tier:1
    };
  }

  $scope.createOrUpdate = function() {
    var cur = $scope.edit.replaces;
    $scope.edit.replaces = -1;
    if(cur == -1) {
      var newpub = jQuery.extend(true, {}, $scope.edit);
      newpub.start.month = _.indexOf(monthNames, $scope.edit.start.month)+1;
      newpub.end.month = _.indexOf(monthNames, $scope.edit.end.month)+1;
      newpub.start.day = parseInt($scope.edit.start.day);
      newpub.end.day = parseInt($scope.edit.end.day);
      $scope.events.push(newpub);
    } else {
      var index = _.indexOf($scope.events, cur);
      $scope.events[index] = jQuery.extend(true, {}, $scope.edit);
      cur = $scope.events[index];
      cur.start.month = _.indexOf(monthNames, $scope.edit.start.month)+1;
      cur.end.month = _.indexOf(monthNames, $scope.edit.end.month)+1;
      cur.start.day = parseInt($scope.edit.start.day);
      cur.end.day = parseInt($scope.edit.end.day);
    }
  }

  $scope.removeCurrent = function() {
    var cur = $scope.edit.replaces;
    $scope.edit.replaces = -1;
    if(cur != -1) {
      $scope.evenets = $scope.events.splice(_.indexOf(events, cur),1);
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

const assert       = require('assert');
const AWS          = require('aws-sdk');
const Crypto       = require('crypto');
const getAWSConfig = require('../aws_config');
const Ironium      = require('../..');
const setup        = require('../helpers');

(getAWSConfig.isAvailable ? describe : describe.skip)('Processing queues - configuration by AWS Credentials object', function() {
  const randomJobID = Crypto.randomBytes(256).toString('hex');
  let runs;
  let accessKeyId;
  let secretAccessKey;
  let credentials;

  function countJobs(job) {
    if (job.id === randomJobID)
      runs++;
    return Promise.resolve();
  }

  before(setup);

  before(function() {
    runs = 0;
  });

  before(function() {
    credentials = new AWS.Credentials(getAWSConfig());

    // Make sure Ironium is using the credentials object
    // and not reading from the environment.
    accessKeyId                       = process.env.AWS_ACCESS_KEY_ID;
    secretAccessKey                   = process.env.AWS_SECRET_ACCESS_KEY;
    process.env.AWS_ACCESS_KEY_ID     = '';
    process.env.AWS_SECRET_ACCESS_KEY = '';
  });

  before(function() {
    Ironium.configure({ credentials, region: 'us-east-1' });
  });

  before(function() {
    Ironium.eachJob('foo', countJobs);
  });

  before(function() {
    return Ironium.queueJob('foo', { id: randomJobID });
  });

  before(function(done) {
    process.env.NODE_ENV = 'production';
    Ironium.start();
    setTimeout(done, 5000);
  });

  it('should be using AWS', function() {
    return Ironium.configPromise
      .then(config => assert.equal(config.service, 'aws'));
  });

  it('should have run the job', function() {
    assert.equal(runs, 1);
  });

  after(function() {
    process.env.AWS_ACCESS_KEY_ID     = accessKeyId;
    process.env.AWS_SECRET_ACCESS_KEY = secretAccessKey;
  });

  after(function() {
    process.env.NODE_ENV = 'test';
    Ironium.stop();
    Ironium.configure({});
  });
});

describe('Processing queues - AWS credentials temporarily unavailable', function() {
  let credentials;
  let refreshedCredentialsCount;

  before(setup);

  before(function() {
    refreshedCredentialsCount = 0;
  });

  before(function() {
    credentials = {
      get(callback) {
        refreshedCredentialsCount++;
        callback(new Error('Getting credentials timed out'));
      }
    };

    Ironium.configure({ credentials, region: 'us-east-1' });
  });

  before(function() {
    Ironium.eachJob('foo', Promise.resolve);
  });

  before(function(done) {
    process.env.NODE_ENV = 'development';
    Ironium.start();
    setTimeout(done, 1000);
  });

  it('should continue to refresh credentials', function() {
    assert(refreshedCredentialsCount > 1, `Expected refreshedCredentialsCount to be > 1, was ${refreshedCredentialsCount}`);
  });

  after(function() {
    process.env.NODE_ENV = 'test';
    Ironium.stop();
    Ironium.configure({});
  });
});
<commit_msg>Fix more leftover state when using SQS.<commit_after>'use strict';

const assert       = require('assert');
const AWS          = require('aws-sdk');
const Crypto       = require('crypto');
const getAWSConfig = require('../aws_config');
const Ironium      = require('../..');
const setup        = require('../helpers');

(getAWSConfig.isAvailable ? describe : describe.skip)('Processing queues - configuration by AWS Credentials object', function() {
  const randomJobID = Crypto.randomBytes(256).toString('hex');
  let runs;
  let accessKeyId;
  let secretAccessKey;
  let credentials;

  function countJobs(job) {
    if (job.id === randomJobID)
      runs++;
    return Promise.resolve();
  }

  before(setup);

  before(function() {
    Ironium._queues._queues.clear();
    Ironium._scheduler._schedules.clear();
  });

  before(function() {
    runs = 0;
  });

  before(function() {
    credentials = new AWS.Credentials(getAWSConfig());

    // Make sure Ironium is using the credentials object
    // and not reading from the environment.
    accessKeyId                       = process.env.AWS_ACCESS_KEY_ID;
    secretAccessKey                   = process.env.AWS_SECRET_ACCESS_KEY;
    process.env.AWS_ACCESS_KEY_ID     = '';
    process.env.AWS_SECRET_ACCESS_KEY = '';
  });

  before(function() {
    Ironium.configure({ credentials, region: 'us-east-1' });
  });

  before(function() {
    Ironium.eachJob('foo', countJobs);
  });

  before(function() {
    return Ironium.queueJob('foo', { id: randomJobID });
  });

  before(function(done) {
    process.env.NODE_ENV = 'production';
    Ironium.start();
    setTimeout(done, 5000);
  });

  it('should be using AWS', function() {
    return Ironium.configPromise
      .then(config => assert.equal(config.service, 'aws'));
  });

  it('should have run the job', function() {
    assert.equal(runs, 1);
  });

  after(function() {
    process.env.AWS_ACCESS_KEY_ID     = accessKeyId;
    process.env.AWS_SECRET_ACCESS_KEY = secretAccessKey;
  });

  after(function() {
    process.env.NODE_ENV = 'test';
    Ironium.stop();
    Ironium.configure({});
  });
});

describe('Processing queues - AWS credentials temporarily unavailable', function() {
  let credentials;
  let refreshedCredentialsCount;

  before(setup);

  before(function() {
    refreshedCredentialsCount = 0;
  });

  before(function() {
    credentials = {
      get(callback) {
        refreshedCredentialsCount++;
        callback(new Error('Getting credentials timed out'));
      }
    };

    Ironium.configure({ credentials, region: 'us-east-1' });
  });

  before(function() {
    Ironium.eachJob('foo', Promise.resolve);
  });

  before(function(done) {
    process.env.NODE_ENV = 'development';
    Ironium.start();
    setTimeout(done, 1000);
  });

  it('should continue to refresh credentials', function() {
    assert(refreshedCredentialsCount > 1, `Expected refreshedCredentialsCount to be > 1, was ${refreshedCredentialsCount}`);
  });

  after(function() {
    process.env.NODE_ENV = 'test';
    Ironium.stop();
    Ironium.configure({});
  });
});
<|endoftext|>


<commit_before>/*
 * eval.js - Evaluate JavaScript code in Discord.
 *
 * Contributed by Ovyerus.
 */

/* eslint-disable no-unused-vars */
const Eris = require('eris');
const util = require('util');
const utils = require(`${__baseDir}/modules/utils.js`);
const fs = require('fs');
const cp = require('child_process');
const path = require('path');
/* eslint-enable */

exports.commands = [
    'eval'
];

exports.eval = {
    desc: 'Evaluate code in Discord.',
    fullDesc: 'Used to evaluate JavaScript code in Discord. Mostly for debug purposes.',
    adminOnly: true,
    usage: '<code>',
    main(bot, ctx) {
        return new Promise((resolve, reject) => {
            if (ctx.suffix.length === 0) {
                ctx.msg.channel.createMessage('Please give arguments to evaluate.').then(resolve).catch(reject);
            } else {
                let evalArgs = ctx.suffix;
                let {msg, args, cmd, suffix, cleanSuffix, guildBot, settings} = ctx; // eslint-disable-line
                try {
                    let returned = eval(evalArgs);

                    let str = util.inspect(returned, {depth: 1});
                    str = str.replace(new RegExp(bot.token, 'gi'), '(token)');

                    let sentMessage = '```js\n';
                    sentMessage += `Input: ${evalArgs}\n\n`;
                    sentMessage += `Output: ${str}\n`;
                    sentMessage += '```';

                    if (sentMessage.length > 1897) {
                        sentMessage = sentMessage.substr(0, 1897);
                        sentMessage = sentMessage + '...\n````';
                    }

                    ctx.msg.channel.createMessage(sentMessage).then(resolve).catch(reject);
                } catch(err) {

                    let errMessage = '```js\n';
                    errMessage += `Input: ${evalArgs}\n\n`;
                    errMessage += `${err}\n`;
                    errMessage += '```';

                    if (errMessage.length > 1897) {
                        errMessage = errMessage.substr(0, 1897);
                        errMessage = errMessage + '...\n```';
                    }

                    ctx.msg.channel.createMessage(errMessage).then(resolve).catch(reject);
                }
            }
        });
    }
};<commit_msg>Rewrite eval and add support for auto-editing for promises<commit_after>/*
 * eval.js - Evaluate JavaScript code in Discord.
 *
 * Contributed by Ovyerus.
 */

/* eslint-disable no-unused-vars */
const Eris = require('eris');
const util = require('util');
const utils = require(`${__baseDir}/modules/utils.js`);
const fs = require('fs');
const cp = require('child_process');
const path = require('path');
const got = require('got');
/* eslint-enable */

const FAILCOL = 0xF44336;
const SUCCESSCOL = 0x8BC34A;

exports.commands = [
    'eval'
];

exports.eval = {
    desc: 'Evaluate code in Discord.',
    fullDesc: 'Used to evaluate JavaScript code in Discord. Mostly for debug purposes.',
    adminOnly: true,
    usage: '<code>',
    main(bot, ctx) {
        return new Promise((resolve, reject) => {
            if (ctx.suffix.length === 0) {
                ctx.msg.channel.createMessage('Please give arguments to evaluate.').then(resolve).catch(reject);
            } else {
                let {msg, args, cmd, suffix, cleanSuffix, guildBot, settings} = ctx; // eslint-disable-line
                try {
                    let returned = eval(ctx.suffix);
                    let str = util.inspect(returned, {depth: 1});
                    str = str.replace(new RegExp(bot.token, 'gi'), '(token)');

                    let embed = {
                        title: 'Evaluation Results',
                        color: SUCCESSCOL,
                        fields: [
                            {name: 'Input', value: generateCodeblock(ctx.suffix)},
                            {name: 'Output', value: generateCodeblock(str)}
                        ]
                    };

                    if (returned instanceof Promise) embed.fields[1].value = generateCodeblock('[object Promise]');

                    if (str.length < 1000) {
                        sendEval(bot, ctx, embed, returned).then(resolve).catch(reject);
                    } else {
                        got('https://hastebin.com/documents', {
                            method: 'POST',
                            body: str
                        }).then(res => {
                            let key = JSON.parse(res.body).key;
                            let url = `https://hastebin.com/${key}.js`;
                            embed.fields[1].value = `Output is too long to display nicely.\nOutput has been uploaded [here](${url})`;

                            return sendEval(bot, ctx, embed, returned);
                        }).then(resolve).catch(reject);
                    }
                } catch(err) {
                    let embed = {
                        title: 'Evaluation Results',
                        color: FAILCOL,
                        fields: [
                            {name: 'Input', value: generateCodeblock(ctx.suffix)},
                            {name: 'Error', value: generateCodeblock(err)}
                        ]
                    };

                    ctx.msg.channel.createMessage({embed}).then(resolve).catch(reject);
                }
            }
        });
    }
};

function generateCodeblock(text) {
    return `\`\`\`js\n${text}\n\`\`\``;
}

function sendEval(bot, ctx, embed, returned) {
    return new Promise((resolve, reject) => {
        let outer;
        ctx.msg.channel.createMessage({embed}).then(m => {
            outer = m;
            if (returned instanceof Promise) {
                return returned;
            } else {
                return null;
            }
        }).then(res => {
            if (!res) {
                resolve();
                return null;
            } else {
                let strN = util.inspect(returned._rejectionHandler0, {depth: 1});
                strN = strN.replace(new RegExp(bot.token, 'gi'), '(token)');

                if (strN.length >= 1000) {
                    return got('https://hastebin.com/documents', {
                        method: 'POST',
                        body: strN
                    });
                } else {
                    return outer.edit({embed: {
                        title: 'Evaluation Results',
                        color: SUCCESSCOL,
                        fields: [
                            {name: 'Input', value: generateCodeblock(ctx.suffix)},
                            {name: 'Output', value: generateCodeblock(strN)}
                        ]
                    }});
                }
            }
        }).then(res => {
            if (!res || res instanceof Eris.Message) return null;

            let key = JSON.parse(res.body).key;
            let url = `https://hastebin.com/${key}.js`;

            return outer.edit({embed: {
                title: 'Evaluation Results',
                color: SUCCESSCOL,
                fields: [
                    {name: 'Input', value: generateCodeblock(ctx.suffix)},
                    {name: 'Output', value: `Output is too long to display nicely.\nOutput has been uploaded [here](${url})`}
                ]
            }});
        }).then(resolve).catch(err => {
            if (err.req && err.req._headers.host === 'discordapp.com') {
                reject(err);
                return null;
            } else {
                return outer.edit({embed: {
                    title: 'Evaluation Results',
                    color: FAILCOL,
                    fields: [
                        {name: 'Input', value: generateCodeblock(ctx.suffix)},
                        {name: 'Error', value: generateCodeblock(err)}
                    ]
                }});
            }
        });
    });
}<|endoftext|>


<commit_before>require('../../support/test_helper');
var assert = require('../../support/assert');
var TestClient = require('../../support/test-client');

function createMapConfig(layers, dataviews, analysis) {
    return {
        version: '1.5.0',
        layers: layers,
        dataviews: dataviews || {},
        analyses: analysis || []
    };
}

describe('formula-dataview: special float values', function() {

    afterEach(function(done) {
        if (this.testClient) {
            this.testClient.drain(done);
        } else {
            done();
        }
    });

    var mapConfig = createMapConfig(
        [
            {
                "type": "cartodb",
                "options": {
                    "source": {
                        "id": "a0"
                    },
                    "cartocss": "#points { marker-width: 10; marker-fill: red; }",
                    "cartocss_version": "2.3.0"
                }
            }
        ],
        {
            val_formula: {
                source: {
                    id: 'a0'
                },
                type: 'formula',
                options: {
                    column: 'val',
                    operation: 'avg'
                }
            }
        },
        [
            {
                "id": "a0",
                "type": "source",
                "params": {
                    "query": [
                        'SELECT',
                        '  null::geometry the_geom_webmercator,',
                        '  CASE',
                        '    WHEN x % 4 = 0 THEN \'infinity\'::float',
                        '    WHEN x % 4 = 1 THEN \'-infinity\'::float',
                        '    WHEN x % 4 = 2 THEN \'NaN\'::float',
                        '    ELSE x',
                        '  END AS val',
                        'FROM generate_series(1, 1000) x'
                    ].join('\n')
                }
            }
        ]
    );

    it('should filter infinities out and count them in the summary', function(done) {
        this.testClient = new TestClient(mapConfig, 1234);
        this.testClient.getDataview('val_formula', {}, function(err, dataview) {
            assert.ok(!err, err);
            assert.equal(dataview.result, 501);
            assert.ok(dataview.infinities === (250 + 250));
            assert.ok(dataview.nans === 250);
            done();
        });
    });
});
<commit_msg>ensuring formula dataview filters infinities, nans and nulls<commit_after>require('../../support/test_helper');
var assert = require('../../support/assert');
var TestClient = require('../../support/test-client');

function createMapConfig(layers, dataviews, analysis) {
    return {
        version: '1.5.0',
        layers: layers,
        dataviews: dataviews || {},
        analyses: analysis || []
    };
}

function getMapConfig(operation, lastNumber) {
    return createMapConfig([
        {
            "type": "cartodb",
            "options": {
                "source": {
                    "id": "a0"
                },
                "cartocss": "#points { marker-width: 10; marker-fill: red; }",
                "cartocss_version": "2.3.0"
            }
        }
    ],
    {
        val_formula: {
            source: {
                id: 'a0'
            },
            type: 'formula',
            options: {
                column: 'val',
                operation: operation
            }
        }
    },
    [
        {
            id: "a0",
            type: "source",
            params: {
                query: `
                    SELECT
                        null::geometry the_geom_webmercator,
                        CASE
                            WHEN x % 5 = 1 THEN 'infinity'::float
                            WHEN x % 5 = 2 THEN '-infinity'::float
                            WHEN x % 5 = 3 THEN 'NaN'::float
                            WHEN x % 5 = 4 THEN NULL
                            ELSE x
                        END AS val
                    FROM generate_series(1, ${lastNumber}) x
                `
            }
        }
    ]);
}

describe('formula-dataview: should filter infinities out and count them in the summary', function() {
    describe('easy numbers', function() { // not needed, but I keep it here to help human calc
        afterEach(function(done) {
            if (this.testClient) {
                this.testClient.drain(done);
            } else {
                done();
            }
        });

        const lastNumber = 10;

        [
            {operation: 'count', result: 2},
            {operation: 'avg', result: 7.5},
            {operation: 'sum', result: 15},
            {operation: 'min', result: 5},
            {operation: 'max', result: 10}
        ]
        .forEach(operationData => {
            it(operationData.operation, function(done) {
                this.testClient = new TestClient(getMapConfig(operationData.operation, lastNumber), 1234);
                this.testClient.getDataview('val_formula', {}, function(err, dataview) {
                    assert.ok(!err, err);
                    assert.deepStrictEqual(dataview, {
                        type: 'formula',
                        operation: operationData.operation,
                        result: operationData.result,
                        nulls: lastNumber / 5,
                        nans: lastNumber / 5,
                        infinities: 2 * lastNumber / 5
                    });
                    done();
                });
            });
        });
    });

    describe('bigger numbers', function() {
        afterEach(function(done) {
            if (this.testClient) {
                this.testClient.drain(done);
            } else {
                done();
            }
        });

        const lastNumber = 1000;

        [
            {operation: 'count', result: 200},
            {operation: 'avg', result: 502.5},
            {operation: 'sum', result: 100500},
            {operation: 'min', result: 5},
            {operation: 'max', result: 1000}
        ]
        .forEach(operationData => {
            it(operationData.operation, function(done) {
                this.testClient = new TestClient(getMapConfig(operationData.operation, lastNumber), 1234);
                this.testClient.getDataview('val_formula', {}, function(err, dataview) {
                    assert.ok(!err, err);
                    assert.deepStrictEqual(dataview, {
                        type: 'formula',
                        operation: operationData.operation,
                        result: operationData.result,
                        nulls: lastNumber / 5,
                        nans: lastNumber / 5,
                        infinities: 2 * lastNumber / 5
                    });
                    done();
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>/**
 * @file A taint item.
 * @module primitives/taint
 */

'use strict'

/**
 * Private members store.
 * @private
 */
const privs = new WeakMap()

/**
 * A taint item.
 * @static
 */
class Taint {
  /**
   * @param {module:primitives/address.Address} source
   *     Source of taint.
   */
  constructor (source) {
    // Validate arguments
    arg.Address(source)

    const priv = {}
    privs.set(this, priv)
    priv.source = source
    priv.recipients = null
    priv.transactions = null
  }

  /**
   * Source of taint.
   * @type {module:primitives/address.Address}
   */
  get source () {
    const priv = privs.get(this)
    const source = priv.source
    return source
  }

  /**
   * Recipients of taint. Excludes source.
   * @type {Set<module:primitives/address.Address>}
   */
  get recipients () {
    const priv = privs.get(this)
    const recipients = priv.recipients
    if (recipients === null) {
      return new Set()
    } else {
      return new Set(recipients)
    }
  }

  /**
   * Tainted addresses. Includes source.
   * @type {Set<module:primitives/address.Address>}
   */
  get addresses () {
    const priv = privs.get(this)
    const source = priv.source
    const recipients = priv.recipients
    if (recipients === null) {
      return new Set([source])
    } else {
      return new Set([source, ...recipients])
    }
  }

  /**
   * Propagating transactions.
   * @type {Set<module:primitives/transaction.Transaction>}
   */
  get transactions () {
    const priv = privs.get(this)
    const transactions = priv.transactions
    if (transactions === null) {
      return new Set()
    } else {
      return new Set(transactions)
    }
  }

  /**
   * Propagating transactions.
   * @type {Set<module:primitives/transaction.Transaction>}
   */
  get txs () {
    return this.transactions
  }

  /**
   * Add recipient.
   * @param {module:primitives/address.Address} recipient
   *     Recipient of taint.
   * @return {module:primitives/taint.Taint}
   *     This instance for chaining.
   */
  addRecipient (recipient) {
    // Validate arguments
    arg.Address(recipient)

    const priv = privs.get(this)
    if (priv.recipients === null) {
      priv.recipients = new Set()
    }
    const recipients = priv.recipients
    recipients.add(recipient)
    return this
  }

  /**
   * Check whether has recipient.
   * @param {module:primitives/address.Address} address
   *     Queried address.
   * @return {boolean} Whether has address as recipient.
   */
  hasRecipient (address) {
    // Validate arguments
    arg.Address(address)

    const priv = privs.get(this)
    const recipients = priv.recipients
    if (recipients === null) {
      return false
    } else {
      return recipients.has(address)
    }
  }

  /**
   * Check whether has address.
   * @param {module:primitives/address.Address} address
   *     Queried address.
   * @return {boolean} Whether has address.
   */
  hasAddress (address) {
    // Validate arguments
    arg.Address(address)

    const priv = privs.get(this)
    const source = priv.source
    if (source === address) {
      return true
    }
    const recipients = priv.recipients
    if (recipients === null) {
      return false
    } else {
      return recipients.has(address)
    }
  }

  /**
   * Add propagating transaction.
   * @param {module:primitives/transaction.Transaction} tx
   *     Propagating transaction.
   * @return {module:primitives/taint.Taint}
   *     This instance for chaining.
   */
  addTransaction (tx) {
    // Validate arguments
    arg.Transaction(tx)

    const priv = privs.get(this)
    if(priv.transactions === null) {
      priv.transactions = new Set()
    }
    const transactions = priv.transactions
    transactions.add(tx)
    return this
  }

  /**
   * Check whether transaction propagated.
   * @param {module:primitives/transaction.Transaction} tx
   *     Queried transaction.
   * @return {boolean} Whether transaction propagated.
   */
  hasTransaction (tx) {
    // Validate arguments
    arg.Transaction(tx)

    const priv = privs.get(this)
    const transactions = priv.transactions
    if (transactions === null) {
      return false
    } else {
      return transactions.has(tx)
    }
  }
}

// Expose
module.exports = Taint

// Circular imports
const arg = require('../util/arg')
<commit_msg>Correct style in Taint#addTransaction<commit_after>/**
 * @file A taint item.
 * @module primitives/taint
 */

'use strict'

/**
 * Private members store.
 * @private
 */
const privs = new WeakMap()

/**
 * A taint item.
 * @static
 */
class Taint {
  /**
   * @param {module:primitives/address.Address} source
   *     Source of taint.
   */
  constructor (source) {
    // Validate arguments
    arg.Address(source)

    const priv = {}
    privs.set(this, priv)
    priv.source = source
    priv.recipients = null
    priv.transactions = null
  }

  /**
   * Source of taint.
   * @type {module:primitives/address.Address}
   */
  get source () {
    const priv = privs.get(this)
    const source = priv.source
    return source
  }

  /**
   * Recipients of taint. Excludes source.
   * @type {Set<module:primitives/address.Address>}
   */
  get recipients () {
    const priv = privs.get(this)
    const recipients = priv.recipients
    if (recipients === null) {
      return new Set()
    } else {
      return new Set(recipients)
    }
  }

  /**
   * Tainted addresses. Includes source.
   * @type {Set<module:primitives/address.Address>}
   */
  get addresses () {
    const priv = privs.get(this)
    const source = priv.source
    const recipients = priv.recipients
    if (recipients === null) {
      return new Set([source])
    } else {
      return new Set([source, ...recipients])
    }
  }

  /**
   * Propagating transactions.
   * @type {Set<module:primitives/transaction.Transaction>}
   */
  get transactions () {
    const priv = privs.get(this)
    const transactions = priv.transactions
    if (transactions === null) {
      return new Set()
    } else {
      return new Set(transactions)
    }
  }

  /**
   * Propagating transactions.
   * @type {Set<module:primitives/transaction.Transaction>}
   */
  get txs () {
    return this.transactions
  }

  /**
   * Add recipient.
   * @param {module:primitives/address.Address} recipient
   *     Recipient of taint.
   * @return {module:primitives/taint.Taint}
   *     This instance for chaining.
   */
  addRecipient (recipient) {
    // Validate arguments
    arg.Address(recipient)

    const priv = privs.get(this)
    if (priv.recipients === null) {
      priv.recipients = new Set()
    }
    const recipients = priv.recipients
    recipients.add(recipient)
    return this
  }

  /**
   * Check whether has recipient.
   * @param {module:primitives/address.Address} address
   *     Queried address.
   * @return {boolean} Whether has address as recipient.
   */
  hasRecipient (address) {
    // Validate arguments
    arg.Address(address)

    const priv = privs.get(this)
    const recipients = priv.recipients
    if (recipients === null) {
      return false
    } else {
      return recipients.has(address)
    }
  }

  /**
   * Check whether has address.
   * @param {module:primitives/address.Address} address
   *     Queried address.
   * @return {boolean} Whether has address.
   */
  hasAddress (address) {
    // Validate arguments
    arg.Address(address)

    const priv = privs.get(this)
    const source = priv.source
    if (source === address) {
      return true
    }
    const recipients = priv.recipients
    if (recipients === null) {
      return false
    } else {
      return recipients.has(address)
    }
  }

  /**
   * Add propagating transaction.
   * @param {module:primitives/transaction.Transaction} tx
   *     Propagating transaction.
   * @return {module:primitives/taint.Taint}
   *     This instance for chaining.
   */
  addTransaction (tx) {
    // Validate arguments
    arg.Transaction(tx)

    const priv = privs.get(this)
    if (priv.transactions === null) {
      priv.transactions = new Set()
    }
    const transactions = priv.transactions
    transactions.add(tx)
    return this
  }

  /**
   * Check whether transaction propagated.
   * @param {module:primitives/transaction.Transaction} tx
   *     Queried transaction.
   * @return {boolean} Whether transaction propagated.
   */
  hasTransaction (tx) {
    // Validate arguments
    arg.Transaction(tx)

    const priv = privs.get(this)
    const transactions = priv.transactions
    if (transactions === null) {
      return false
    } else {
      return transactions.has(tx)
    }
  }
}

// Expose
module.exports = Taint

// Circular imports
const arg = require('../util/arg')
<|endoftext|>


<commit_before>describe('iD.rendererBackgroundSource', function() {
    it('does not error with blank template', function() {
        var source = iD.rendererBackgroundSource({ template: '' });
        expect(source.url([0,1,2])).to.equal('');
    });

    it('supports tms replacement tokens', function() {
        var source = iD.rendererBackgroundSource({
            type: 'tms',
            template: '{z}/{x}/{y}'
        });
        expect(source.url([0,1,2])).to.equal('2/0/1');
    });

    it('supports wms replacement tokens', function() {
        var source = iD.rendererBackgroundSource({
            type: 'wms',
            projection: 'EPSG:3857',
            template: 'SRS={proj}&imageSR={wkid}&bboxSR={wkid}&FORMAT=image/jpeg&WIDTH={width}&HEIGHT={height}&BBOX={bbox}'
        });

        var result = iD.utilStringQs(source.url([0,1,2]));
        expect(result.SRS).to.equal('EPSG:3857');
        expect(result.imageSR).to.equal('3857');
        expect(result.bboxSR).to.equal('3857');
        expect(result.FORMAT).to.equal('image/jpeg');
        expect(result.WIDTH).to.equal('256');
        expect(result.HEIGHT).to.equal('256');

        var bbox = result.BBOX.split(',');
        expect(+bbox[0]).to.be.closeTo(-20037508.34, 1e-3);
        expect(+bbox[1]).to.be.closeTo(0, 1e-3);
        expect(+bbox[2]).to.be.closeTo(-10018754.17, 1e-3);
        expect(+bbox[3]).to.be.closeTo(10018754.17, 1e-3);
    });

    it('supports subdomains', function() {
        var source = iD.rendererBackgroundSource({ template: '{switch:a,b}/{z}/{x}/{y}'});
        expect(source.url([0,1,2])).to.equal('b/2/0/1');
    });

    it('distributes requests between subdomains', function() {
        var source = iD.rendererBackgroundSource({ template: '{switch:a,b}/{z}/{x}/{y}' });
        expect(source.url([0,1,1])).to.equal('b/1/0/1');
        expect(source.url([0,2,1])).to.equal('a/1/0/2');
    });

    it('correctly displays an overlay with no overzoom specified', function() {
        var source = iD.rendererBackgroundSource({ zoomExtent: [6,16] });
        expect(source.validZoom(10)).to.be.true;
        expect(source.validZoom(3)).to.be.false;
        expect(source.validZoom(17)).to.be.true;
    });

    it('correctly displays an overlay with an invalid overzoom', function() {
        var source = iD.rendererBackgroundSource({ zoomExtent: [6,16], overzoom: 'gibberish'});
        expect(source.validZoom(10)).to.be.true;
        expect(source.validZoom(3)).to.be.false;
        expect(source.validZoom(17)).to.be.true;
    });

    it('correctly displays an overlay with overzoom:true', function() {
        var source = iD.rendererBackgroundSource({ zoomExtent: [6,16], overzoom: true});
        expect(source.validZoom(10)).to.be.true;
        expect(source.validZoom(3)).to.be.false;
        expect(source.validZoom(17)).to.be.true;
    });

    it('correctly displays an overlay with overzoom:false', function() {
        var source = iD.rendererBackgroundSource({ zoomExtent: [6,16], overzoom: false});
        expect(source.validZoom(10)).to.be.true;
        expect(source.validZoom(3)).to.be.false;
        expect(source.validZoom(17)).to.be.false;
    });
});
<commit_msg>Fix the domain switch test<commit_after>describe('iD.rendererBackgroundSource', function() {
    it('does not error with blank template', function() {
        var source = iD.rendererBackgroundSource({ template: '' });
        expect(source.url([0,1,2])).to.equal('');
    });

    it('supports tms replacement tokens', function() {
        var source = iD.rendererBackgroundSource({ type: 'tms', template: '{z}/{x}/{y}' });
        expect(source.url([0,1,2])).to.equal('2/0/1');
    });

    it('supports wms replacement tokens', function() {
        var source = iD.rendererBackgroundSource({
            type: 'wms',
            projection: 'EPSG:3857',
            template: 'SRS={proj}&imageSR={wkid}&bboxSR={wkid}&FORMAT=image/jpeg&WIDTH={width}&HEIGHT={height}&BBOX={bbox}'
        });

        var result = iD.utilStringQs(source.url([0,1,2]));
        expect(result.SRS).to.equal('EPSG:3857');
        expect(result.imageSR).to.equal('3857');
        expect(result.bboxSR).to.equal('3857');
        expect(result.FORMAT).to.equal('image/jpeg');
        expect(result.WIDTH).to.equal('256');
        expect(result.HEIGHT).to.equal('256');

        var bbox = result.BBOX.split(',');
        expect(+bbox[0]).to.be.closeTo(-20037508.34, 1e-3);
        expect(+bbox[1]).to.be.closeTo(0, 1e-3);
        expect(+bbox[2]).to.be.closeTo(-10018754.17, 1e-3);
        expect(+bbox[3]).to.be.closeTo(10018754.17, 1e-3);
    });

    it('supports subdomains', function() {
        var source = iD.rendererBackgroundSource({ type: 'tms', template: '{switch:a,b}/{z}/{x}/{y}' });
        expect(source.url([0,1,2])).to.equal('b/2/0/1');
    });

    it('distributes requests between subdomains', function() {
        var source = iD.rendererBackgroundSource({ type: 'tms', template: '{switch:a,b}/{z}/{x}/{y}' });
        expect(source.url([0,1,1])).to.equal('b/1/0/1');
        expect(source.url([0,2,1])).to.equal('a/1/0/2');
    });

    it('correctly displays an overlay with no overzoom specified', function() {
        var source = iD.rendererBackgroundSource({ zoomExtent: [6,16] });
        expect(source.validZoom(10)).to.be.true;
        expect(source.validZoom(3)).to.be.false;
        expect(source.validZoom(17)).to.be.true;
    });

    it('correctly displays an overlay with an invalid overzoom', function() {
        var source = iD.rendererBackgroundSource({ zoomExtent: [6,16], overzoom: 'gibberish'});
        expect(source.validZoom(10)).to.be.true;
        expect(source.validZoom(3)).to.be.false;
        expect(source.validZoom(17)).to.be.true;
    });

    it('correctly displays an overlay with overzoom:true', function() {
        var source = iD.rendererBackgroundSource({ zoomExtent: [6,16], overzoom: true});
        expect(source.validZoom(10)).to.be.true;
        expect(source.validZoom(3)).to.be.false;
        expect(source.validZoom(17)).to.be.true;
    });

    it('correctly displays an overlay with overzoom:false', function() {
        var source = iD.rendererBackgroundSource({ zoomExtent: [6,16], overzoom: false});
        expect(source.validZoom(10)).to.be.true;
        expect(source.validZoom(3)).to.be.false;
        expect(source.validZoom(17)).to.be.false;
    });
});
<|endoftext|>


<commit_before>/*
 *  action_up_down.js
 *
 *  David Janes
 *  IOTDB.org
 *  2016-09-22
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

const assert = require("assert");
const helpers = require("./helpers");

const iotdb_thing = require("..");

describe("action_up_down", function() {
    describe("action:turn on", function() {
        const action = "turn up";

        it("thing:all", function(done) {
            const thing = null;

            helpers.run({
                action: action,
                thing: thing,
            }, (error, matches) => {
                try {
                    assert.ok(!error, "no error expected");
                    assert.strictEqual(matches.length, 6);

                    {
                        const r_thing = helpers.select(matches, 'thing-basement-heater');
                        const r_value = r_thing.ostate.temperature;
                        const x_value = 20.5;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-main-thermometer');
                        const r_value = r_thing.ostate.tem;
                        const x_value = 70.5;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-main-tv');
                        const r_value = r_thing.ostate.volume;
                        const x_value = 70;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-ac');
                        const r_value = r_thing.ostate.t;
                        const x_value = 16.5;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-lighting');
                        const r_value = r_thing.ostate.brightness;
                        const x_value = 20;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-tv-on');
                        const r_value = r_thing.ostate['volume-up'];
                        assert.ok(r_value);
                    }

                    done();
                }
                catch (x) {
                    done(x);
                }
            });
        });
        it("thing:TV", function(done) {
            const thing = "TV";

            helpers.run({
                action: action,
                thing: thing,
            }, (error, matches) => {
                try {
                    assert.ok(!error, "no error expected");
                    assert.strictEqual(matches.length, 2);
                    {
                        const r_thing = helpers.select(matches, 'thing-main-tv');
                        const r_value = r_thing.ostate.volume;
                        const x_value = 70;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-tv-on');
                        const r_value = r_thing.ostate['volume-up'];
                        assert.ok(r_value);
                    }
                    done();
                }
                catch (x) {
                    done(x);
                }
            });
        });
    });
});

<commit_msg>turn down<commit_after>/*
 *  action_up_down.js
 *
 *  David Janes
 *  IOTDB.org
 *  2016-09-22
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

const assert = require("assert");
const helpers = require("./helpers");

const iotdb_thing = require("..");

describe("action_up_down", function() {
    describe("action:turn on", function() {
        const action = "turn up";

        it("thing:all", function(done) {
            const thing = null;

            helpers.run({
                action: action,
                thing: thing,
            }, (error, matches) => {
                try {
                    assert.ok(!error, "no error expected");
                    assert.strictEqual(matches.length, 6);

                    {
                        const r_thing = helpers.select(matches, 'thing-basement-heater');
                        const r_value = r_thing.ostate.temperature;
                        const x_value = 20.5;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-main-thermometer');
                        const r_value = r_thing.ostate.tem;
                        const x_value = 70.5;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-main-tv');
                        const r_value = r_thing.ostate.volume;
                        const x_value = 70;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-ac');
                        const r_value = r_thing.ostate.t;
                        const x_value = 16.5;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-lighting');
                        const r_value = r_thing.ostate.brightness;
                        const x_value = 20;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-tv-on');
                        const r_value = r_thing.ostate['volume-up'];
                        assert.ok(r_value);
                    }

                    done();
                }
                catch (x) {
                    done(x);
                }
            });
        });
        it("thing:TV", function(done) {
            const thing = "TV";

            helpers.run({
                action: action,
                thing: thing,
            }, (error, matches) => {
                try {
                    assert.ok(!error, "no error expected");
                    assert.strictEqual(matches.length, 2);
                    {
                        const r_thing = helpers.select(matches, 'thing-main-tv');
                        const r_value = r_thing.ostate.volume;
                        const x_value = 70;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-tv-on');
                        const r_value = r_thing.ostate['volume-up'];
                        assert.ok(r_value);
                    }
                    done();
                }
                catch (x) {
                    done(x);
                }
            });
        });
    });
    describe("action:turn down", function() {
        const action = "turn down";

        it("thing:all", function(done) {
            const thing = null;

            helpers.run({
                action: action,
                thing: thing,
            }, (error, matches) => {
                try {
                    assert.ok(!error, "no error expected");
                    assert.strictEqual(matches.length, 6);

                    {
                        const r_thing = helpers.select(matches, 'thing-basement-heater');
                        const r_value = r_thing.ostate.temperature;
                        const x_value = 19.5;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-main-thermometer');
                        const r_value = r_thing.ostate.tem;
                        const x_value = 69.5;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-main-tv');
                        const r_value = r_thing.ostate.volume;
                        const x_value = 30;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-ac');
                        const r_value = r_thing.ostate.t;
                        const x_value = 15.5;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-lighting');
                        const r_value = r_thing.ostate.brightness;
                        const x_value = 0;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-tv-off');
                        const r_value = r_thing.ostate['volume-down'];
                        assert.ok(r_value);
                    }

                    done();
                }
                catch (x) {
                    done(x);
                }
            });
        });
        it("thing:TV", function(done) {
            const thing = "TV";

            helpers.run({
                action: action,
                thing: thing,
            }, (error, matches) => {
                try {
                    assert.ok(!error, "no error expected");
                    assert.strictEqual(matches.length, 2);
                    {
                        const r_thing = helpers.select(matches, 'thing-main-tv');
                        const r_value = r_thing.ostate.volume;
                        const x_value = 30;
                        assert.deepEqual(r_value, x_value);
                    }
                    {
                        const r_thing = helpers.select(matches, 'thing-master-tv-off');
                        const r_value = r_thing.ostate['volume-down'];
                        assert.ok(r_value);
                    }
                    done();
                }
                catch (x) {
                    done(x);
                }
            });
        });
    });
});
<|endoftext|>