<commit_before>var webSocket;
var floorData = [];
var rangeSlider;

function showRecentPastData(time){
    var numOfFloors = floorData.length;
    var tmp = 11-time;
    for (var i = 0; i < numOfFloors; i++) {
        var index = floorData[i].length-tmp;
        displyaData(i+1,floorData[i][index]);
    }

}

function createDataArrays(val){
    for (var i = 0; i < val; i++) {
        floorData[i] = [];
    }
}

function createWebSocket(host) {

    if (!("WebSocket" in window)) {
        console.log("browser doens't support");
        //add meaningful message
    } else {
        //The user has WebSockets
        console.log("browser support");

        connect();

        function connect() {
            try {

                webSocket = new WebSocket(host);

                webSocket.onopen = function () {
                    console.log("on open");
                };

                webSocket.onmessage = function (msg) {
                    console.log("on message");
                    reatTimeDataHandler(JSON.parse(msg.data));

                };

                webSocket.onclose = function () {
                    console.log("on close");
                };

                webSocket.error= function (err) {
                    console.log(err);
                }

            } catch (exception) {
                console.log(exception);
            }

        }

    }
}

function reatTimeDataHandler(data){
    rangeSlider.bootstrapSlider('setValue', 10);
    var buildingId = getUrlVar("buildingId");
    if(data.building === "WSO2"){
        var floorId = data.floor;
        if(data.floor==="5th floor"){
            floorId="1";
        }
        var fId = parseInt(floorId)-1;
        if (floorData[fId].length==10){
            floorData[fId].shift();
            floorData[fId].push(data);
        }else{
            floorData[fId].push(data);
        }
        displyaData(floorId,data);
    }
}

function getUrlVar(key){
    var result = new RegExp(key + "=([^&]*)", "i").exec(window.location.search);
    return result && unescape(result[1]) || "";
}

function displyaData(floorId,data){

    var canvas = document.getElementById(floorId);
    clearCanvas(canvas);
    var ctx = canvas.getContext("2d");
    if (data!=null){
        ctx.font = "14px Arial";
        ctx.fillText("Temperature: " + data.temperature,10,10);
        ctx.fillText("Air Quality: " + data.airQuality,10,30);
        ctx.fillText("Humidity: " + data.humidity,10,50);
        ctx.fillText("Light: " + data.light,10,70);
        ctx.fillText("Motion: " + data.motion,10,90);
    }else{
        ctx.font = "14px Arial";
        ctx.fillText("No value",10,10);
    }

}

function clearCanvas(cnv) {
    var ctx = cnv.getContext('2d');     // gets reference to canvas context
    ctx.beginPath();    // clear existing drawing paths
    ctx.save();         // store the current transformation matrix

    // Use the identity matrix while clearing the canvas
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, cnv.width, cnv.height);

    ctx.restore();        // restore the transform
}

var getProviderData = function (tableName, timeFrom, timeTo, start, limit, sortBy) {
    var providerData = null;
    var providerUrl = context + '/api/batch-provider?action=getLatestUpdate&tableName=' + tableName;

    if (timeFrom && timeTo) {
        providerUrl += '&timeFrom=' + timeFrom + '&timeTo=' + timeTo;
    }
    if (start) {
        providerUrl += "&start=" + start;
    }
    if (limit) {
        providerUrl += "&limit=" + limit;
    }
    if (sortBy) {
        providerUrl += "&sortBy="  +sortBy
    }
    $.ajax({
        url:providerUrl,
        method: "GET",
        contentType: "application/json",
        async: false,
        success: function (data) {
            providerData = data;
        },
        error : function (err) {
            console.log(err);
        }
    });
    return providerData;
};

function getRecentPastdata(numOfFloors){
    var currentTime = new Date();
    var oldTime = currentTime.getTime();
    currentTime.setMinutes(currentTime.getMinutes() - 30);

    for (var x=0; x<numOfFloors;x++){
        floorData[x]= getProviderData("ORG_WSO2_FLOOR_PERFLOOR_SENSORSTREAM", currentTime.getTime(), oldTime, 0, 10, "DESC").reverse();

    }
    showRecentPastData(10);

}

$(document).ready(function () {

    $(".slider-wrapper").show(1000);

    rangeSlider = $("#range-slider").bootstrapSlider();
    rangeSlider.bootstrapSlider('setAttribute', 'min', 1);
    rangeSlider.bootstrapSlider('setValue', 10);
    var analyticsUrl = "wss://localhost:9445";
    $.ajax({
        url:context + '/api/analytics/',
        method: "GET",
        contentType: "application/json",
        async: false,
        success: function (data) {
            analyticsUrl = data;
        },
        error : function (err) {
        }
    });
    var url = analyticsUrl + "/outputwebsocket/Floor-Analysis-WebSocketLocal-FloorEvent";
    var numOfFloors = $("#buildingView").data("num_of_floors");

    createWebSocket(url);
    createDataArrays(numOfFloors);
    getRecentPastdata(numOfFloors);

    $('#range-slider').on("slide", function () {}).on("change", function () {
        var time = rangeSlider.bootstrapSlider("getValue");
        showRecentPastData(time);
    });

    $('input[name="daterange"]').datepicker({
        orientation: "auto",
        endDate: "+0d"
    }).on("changeDate", function (e) {

    });

    $("#historic-toggle").click(function () {
        $(".date-picker").slideToggle("slow");
    });

});

window.onbeforeunload = function () {
    if (webSocket) {
        webSocket.close();
    }
};<commit_msg>resolve conflicts<commit_after>var webSocket;
var floorData = [];
var rangeSlider;
var timer;
var sliderPoint = 1;
var sliderPointMax = 10;
var sliderPointMin = 1;

function showRecentPastData(time) {
    var numOfFloors = floorData.length;
    var tmp = sliderPointMax + 1 - time;
    for (var i = 0; i < numOfFloors; i++) {
        var index = floorData[i].length - tmp;
        displyaData(i + 1, floorData[i][index]);
    }
}

function createDataArrays(val) {
    for (var i = 0; i < val; i++) {
        floorData[i] = [];
    }
}

function createWebSocket(host) {

    if (!("WebSocket" in window)) {
        console.log("browser doens't support");
        //add meaningful message
    } else {
        //The user has WebSockets
        console.log("browser support");

        connect();

        function connect() {
            try {

                webSocket = new WebSocket(host);

                webSocket.onopen = function () {
                    console.log("on open");
                };
                webSocket.onmessage = function (msg) {
                    console.log("on message");
                    realTimeDataHandler(JSON.parse(msg.data));
                };
                webSocket.onclose = function () {
                    console.log("on close");
                };
                webSocket.error = function (err) {
                    console.log(err);
                }

            } catch (exception) {
                console.log(exception);
            }

        }

    }
}

function realTimeDataHandler(data) {
    rangeSlider.bootstrapSlider('setValue', sliderPointMax);
    var buildingId = getUrlVar("buildingId");
    if (data.building === buildingId) {
        var floorId = data.floor;
        // if (data.floor === "5th floor") {
        //     floorId = "1";
        // }
        var fId = parseInt(floorId) - 1;
        if (floorData[fId].length == 10) {
            floorData[fId].shift();
            floorData[fId].push(data);
        } else {
            floorData[fId].push(data);
        }
        displyaData(floorId, data);
    }
}

function getUrlVar(key) {
    var result = new RegExp(key + "=([^&]*)", "i").exec(window.location.search);
    return result && unescape(result[1]) || "";
}

function displyaData(floorId, data) {

    var canvas = document.getElementById(floorId);
    clearCanvas(canvas);
    var ctx = canvas.getContext("2d");
    if (data != null) {
        ctx.font = "14px Arial";
        ctx.fillText("Temperature: " + data.temperature, 10, 10);
        ctx.fillText("Air Quality: " + data.airQuality, 10, 30);
        ctx.fillText("Humidity: " + data.humidity, 10, 50);
        ctx.fillText("Light: " + data.light, 10, 70);
        ctx.fillText("Motion: " + data.motion, 10, 90);
    } else {
        ctx.font = "14px Arial";
        ctx.fillText("No value", 10, 10);
    }
}

function clearCanvas(cnv) {
    var ctx = cnv.getContext('2d');     // gets reference to canvas context
    ctx.beginPath();    // clear existing drawing paths
    ctx.save();         // store the current transformation matrix

    // Use the identity matrix while clearing the canvas
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, cnv.width, cnv.height);

    ctx.restore();        // restore the transform
}

var getProviderData = function (tableName, timeFrom, timeTo, start, limit, sortBy) {
    var providerData = null;
    var providerUrl = context + '/api/batch-provider?action=getLatestUpdate&tableName=' + tableName;

    if (timeFrom && timeTo) {
        providerUrl += '&timeFrom=' + timeFrom + '&timeTo=' + timeTo;
    }
    if (start) {
        providerUrl += "&start=" + start;
    }
    if (limit) {
        providerUrl += "&limit=" + limit;
    }
    if (sortBy) {
        providerUrl += "&sortBy=" + sortBy
    }
    $.ajax({
        url: providerUrl,
        method: "GET",
        contentType: "application/json",
        async: false,
        success: function (data) {
            providerData = data;
        },
        error: function (err) {
            console.log(err);
        }
    });
    return providerData;
};

function slide() {
    if (sliderPoint <= sliderPointMax) {
        rangeSlider.bootstrapSlider('setValue', sliderPoint);
        showRecentPastData(sliderPoint);
        sliderPoint++;
    } else {
        sliderPoint = sliderPointMax;
        setTimer();
    }
}

function setTimer() {
    if (timer) {
        // stop
        showRecentPastData(sliderPoint);
        rangeSlider.bootstrapSlider('setValue', sliderPoint);
        clearInterval(timer);
        timer = null;
        if (sliderPoint == sliderPointMax) {
            sliderPoint = sliderPointMin;
        }
    }
    else {
        timer = setInterval("slide()", 1000);
    }
}

function getRecentPastdata(numOfFloors) {
    var currentTime = new Date();
    var oldTime = currentTime.getTime();
    currentTime.setMinutes(currentTime.getMinutes() - 30);

    for (var x = 0; x < numOfFloors; x++) {
        floorData[x] = getProviderData("ORG_WSO2_FLOOR_PERFLOOR_SENSORSTREAM", currentTime.getTime(), oldTime, 0, 10, "DESC").reverse();
    }
    showRecentPastData(sliderPointMax);
}

function setRealViewSlider(){
    rangeSlider = $("#range-slider").bootstrapSlider();
    rangeSlider.bootstrapSlider('setAttribute', 'min', sliderPointMin);
    rangeSlider.bootstrapSlider('setValue', sliderPointMax);

}

$("#pla").on("click", "i", function (event) {
    setTimer();
});

$(document).ready(function () {

    $(".slider-wrapper").show(1000);

    setRealViewSlider();

    var analyticsUrl = "wss://localhost:9445";
    $.ajax({
        url:context + '/api/analytics/',
        method: "GET",
        contentType: "application/json",
        async: false,
        success: function (data) {
            analyticsUrl = data;
        },
        error : function (err) {
        }
    });

    var url = analyticsUrl + '/outputwebsocket/Floor-Analysis-WebSocketLocal-FloorEvent';
    var numOfFloors = $("#buildingView").data("num_of_floors");

    createWebSocket(url);
    createDataArrays(numOfFloors);
    getRecentPastdata(numOfFloors);

    $('#range-slider').on("slide", function () {
    }).on("change", function () {
        var time = rangeSlider.bootstrapSlider("getValue");
        showRecentPastData(time);
    });

    $('input[name="daterange"]').datepicker({
        orientation: "auto",
        endDate: "+0d"
    }).on("changeDate", function (e) {

    });

    $("#historic-toggle").click(function () {
        $(".date-picker").slideToggle("slow");
    });
});

window.onbeforeunload = function () {
    if (webSocket) {
        webSocket.close();
    }
};<|endoftext|>


<commit_before>define(["underscore", "traveler", "elevator"], function(_, Traveler, Elevator) {
    var Chance = require("chance");
    var seedrandom = require("seedrandom");
    var maxFloors = 12;
    var maxTravelerPeak = 10;

    function isEmptyState(systemState) {
        var elevatorsBusy = _.filter(systemState.elevators, function(item) {
            return item.state !== "still" || item.pushedButtons.length > 0 || item.travelers.length > 0;
        });
        return systemState.callingFloors.length == 0 && elevatorsBusy.length == 0;
    }

    function getRandomCount(currentTick, maxAtTime, devTime, maxCount) {
        if (currentTick >= maxAtTime - devTime && currentTick <= maxAtTime + devTime) {
            if (currentTick == maxAtTime) {
                return maxCount;
            } else if (currentTick < maxAtTime) {
                return maxCount - parseInt(((maxAtTime - currentTick) / devTime) * maxCount);
            } else if (currentTick > maxAtTime) {
                return maxCount - parseInt(((currentTick - maxAtTime) / devTime) * maxCount);
            }
        } else {
            return 0;
        }
    }

    return function(options) {
        var seed = (options.randomseed) ? options.randomseed : +Date();
        var rng = seedrandom(seed, {global: true});
        var chance = new Chance(seed);

        function getName() {
            return chance.name();
        }

        this.isFinished = function(currentTick, systemState) {
            // End if more than 50 ticks have passed or if the system state is empty after 3 ticks
            return /*currentTick > 50 || */(currentTick > 30 && isEmptyState(systemState));
        }
        this.getElevatorSetup = function(stats) {
            return [
                new Elevator("HISS 1", 0, maxFloors, 2, 3, stats),
                new Elevator("HISS 2", 0, maxFloors, 2, 3, stats),
                new Elevator("HISS 3", 0, maxFloors, 2, 3, stats)
            ];
        }
        this.onTick = function(tick, system) {
            // 10 per hour
            // Around 10 = morning
            // Around 90 = dinner
            var morningCount = getRandomCount(tick, 10, 5, maxTravelerPeak);
            var dinnerCount = getRandomCount(tick, 90, 5, maxTravelerPeak);
            for(var i = 0; i < morningCount + dinnerCount; i++) {
                system.addTraveler(new Traveler(getName(), 0, 2 + parseInt(Math.random() * (maxFloors - 2))));
            }
            if (tick > 15 && tick < 95) {
                // Random spawn travelers during the day
                var count = parseInt(Math.random() * 2);
                for(var i = 0; i < count; i++) {
                    var from = parseInt(Math.random() * maxFloors);
                    var to = parseInt(Math.random() * maxFloors);
                    if (to === from) {
                        to = (from + 1) % maxFloors;
                    }
                    system.addTraveler(new Traveler(getName(), from, to));
                }
            }
        }
    };
});
<commit_msg>Remove ugly code<commit_after>define(["underscore", "traveler", "elevator"], function(_, Traveler, Elevator) {
    var Chance = require("chance");
    var seedrandom = require("seedrandom");
    var maxFloors = 12;
    var maxTravelerPeak = 10;

    function isEmptyState(systemState) {
        var elevatorsBusy = _.filter(systemState.elevators, function(item) {
            return item.state !== "still" || item.pushedButtons.length > 0 || item.travelers.length > 0;
        });
        return systemState.callingFloors.length == 0 && elevatorsBusy.length == 0;
    }

    function getRandomCount(currentTick, maxAtTime, devTime, maxCount) {
        if (currentTick >= maxAtTime - devTime && currentTick <= maxAtTime + devTime) {
            if (currentTick == maxAtTime) {
                return maxCount;
            } else if (currentTick < maxAtTime) {
                return maxCount - parseInt(((maxAtTime - currentTick) / devTime) * maxCount);
            } else if (currentTick > maxAtTime) {
                return maxCount - parseInt(((currentTick - maxAtTime) / devTime) * maxCount);
            }
        } else {
            return 0;
        }
    }

    return function(options) {
        var seed = (options.randomseed) ? options.randomseed : +Date();
        var rng = seedrandom(seed, {global: true});
        var chance = new Chance(seed);

        function getName() {
            return chance.name();
        }

        this.isFinished = function(currentTick, systemState) {
            // End if more than 50 ticks have passed or if the system state is empty after 3 ticks
            return currentTick > 30 && isEmptyState(systemState);
        }

        this.getElevatorSetup = function(stats) {
            return [
                new Elevator("HISS 1", 0, maxFloors, 2, 3, stats),
                new Elevator("HISS 2", 0, maxFloors, 2, 3, stats),
                new Elevator("HISS 3", 0, maxFloors, 2, 3, stats)
            ];
        }

        this.onTick = function(tick, system) {
            // 10 per hour
            // Around 10 = morning
            // Around 90 = dinner
            var morningCount = getRandomCount(tick, 10, 5, maxTravelerPeak);
            var dinnerCount = getRandomCount(tick, 90, 5, maxTravelerPeak);
            for(var i = 0; i < morningCount + dinnerCount; i++) {
                system.addTraveler(new Traveler(getName(), 0, 2 + parseInt(Math.random() * (maxFloors - 2))));
            }
            if (tick > 15 && tick < 95) {
                // Random spawn travelers during the day
                var count = parseInt(Math.random() * 2);
                for(var i = 0; i < count; i++) {
                    var from = parseInt(Math.random() * maxFloors);
                    var to = parseInt(Math.random() * maxFloors);
                    if (to === from) {
                        to = (from + 1) % maxFloors;
                    }
                    system.addTraveler(new Traveler(getName(), from, to));
                }
            }
        }
    };
});
<|endoftext|>


<commit_before>define(["underscore", "traveler", "elevator"], function(_, Traveler, Elevator) {
    var Chance = require("chance");
    var seedrandom = require("seedrandom");
    var maxFloors = 4;

    function isEmptyState(systemState) {
        var elevatorsBusy = _.filter(systemState.elevators, function(item) {
            return item.state !== "still" || item.pushedButtons.length > 0 || item.travelers.length > 0;
        });
        return systemState.callingFloors.length == 0 && elevatorsBusy.length == 0;
    }

    function getRandomCount(currentTick, maxAtTime, devTime, maxCount) {
        if (currentTick >= maxAtTime - devTime && currentTick <= maxAtTime + devTime) {
            if (currentTick == maxAtTime) {
                return maxCount;
            } else if (currentTick < maxAtTime) {
                return maxCount - parseInt(((maxAtTime - currentTick) / devTime) * maxCount);
            } else if (currentTick > maxAtTime) {
                return maxCount - parseInt(((currentTick - maxAtTime) / devTime) * maxCount);
            }
        } else {
            return 0;
        }
    }

    return function(options) {
        var seed = (options.randomseed) ? options.randomseed : +Date();
        var rng = seedrandom(seed, {global: true});
        var chance = new Chance(seed);

        function getName() {
            return chance.name();
        }

        this.isFinished = function(currentTick, systemState) {
            // End if more than 50 ticks have passed or if the system state is empty after 3 ticks
            return /*currentTick > 50 || */(currentTick > 30 && isEmptyState(systemState));
        }
        this.getElevatorSetup = function(stats) {
            return [
                new Elevator("HISS 1", 0, maxFloors, 2, 3, stats),
                new Elevator("HISS 2", 0, maxFloors, 2, 3, stats),
                new Elevator("HISS 3", 0, maxFloors, 2, 3, stats)
            ];
        }
        this.onTick = function(tick, system) {
            // 20 per hour
            // Around 20 = morning
            // Around 180 = dinner
            var morningCount = getRandomCount(tick, 20, 10, 5);
            var dinnerCount = getRandomCount(tick, 180, 10, 5);
            for(var i = 0; i < morningCount + dinnerCount; i++) {
                system.addTraveler(new Traveler(getName(), 0, 2 + parseInt(Math.random() * (maxFloors - 2))));
            }
            if (tick > 30 && tick < 170) {
                // Random spawn travelers during the day
                var count = parseInt(Math.random() * 2);
                for(var i = 0; i < count; i++) {
                    var from = parseInt(Math.random() * maxFloors);
                    var to = parseInt(Math.random() * maxFloors);
                    if (to === from) {
                        to = (from + 1) % maxFloors;
                    }
                    system.addTraveler(new Traveler(getName(), from, to));
                }
            }
        }
    };
});
<commit_msg>Improve office scenario<commit_after>define(["underscore", "traveler", "elevator"], function(_, Traveler, Elevator) {
    var Chance = require("chance");
    var seedrandom = require("seedrandom");
    var maxFloors = 12;
    var maxTravelerPeak = 10;

    function isEmptyState(systemState) {
        var elevatorsBusy = _.filter(systemState.elevators, function(item) {
            return item.state !== "still" || item.pushedButtons.length > 0 || item.travelers.length > 0;
        });
        return systemState.callingFloors.length == 0 && elevatorsBusy.length == 0;
    }

    function getRandomCount(currentTick, maxAtTime, devTime, maxCount) {
        if (currentTick >= maxAtTime - devTime && currentTick <= maxAtTime + devTime) {
            if (currentTick == maxAtTime) {
                return maxCount;
            } else if (currentTick < maxAtTime) {
                return maxCount - parseInt(((maxAtTime - currentTick) / devTime) * maxCount);
            } else if (currentTick > maxAtTime) {
                return maxCount - parseInt(((currentTick - maxAtTime) / devTime) * maxCount);
            }
        } else {
            return 0;
        }
    }

    return function(options) {
        var seed = (options.randomseed) ? options.randomseed : +Date();
        var rng = seedrandom(seed, {global: true});
        var chance = new Chance(seed);

        function getName() {
            return chance.name();
        }

        this.isFinished = function(currentTick, systemState) {
            // End if more than 50 ticks have passed or if the system state is empty after 3 ticks
            return /*currentTick > 50 || */(currentTick > 30 && isEmptyState(systemState));
        }
        this.getElevatorSetup = function(stats) {
            return [
                new Elevator("HISS 1", 0, maxFloors, 2, 3, stats),
                new Elevator("HISS 2", 0, maxFloors, 2, 3, stats),
                new Elevator("HISS 3", 0, maxFloors, 2, 3, stats)
            ];
        }
        this.onTick = function(tick, system) {
            // 10 per hour
            // Around 10 = morning
            // Around 90 = dinner
            var morningCount = getRandomCount(tick, 10, 5, maxTravelerPeak);
            var dinnerCount = getRandomCount(tick, 90, 5, maxTravelerPeak);
            for(var i = 0; i < morningCount + dinnerCount; i++) {
                system.addTraveler(new Traveler(getName(), 0, 2 + parseInt(Math.random() * (maxFloors - 2))));
            }
            if (tick > 15 && tick < 95) {
                // Random spawn travelers during the day
                var count = parseInt(Math.random() * 2);
                for(var i = 0; i < count; i++) {
                    var from = parseInt(Math.random() * maxFloors);
                    var to = parseInt(Math.random() * maxFloors);
                    if (to === from) {
                        to = (from + 1) % maxFloors;
                    }
                    system.addTraveler(new Traveler(getName(), from, to));
                }
            }
        }
    };
});
<|endoftext|>


<commit_before>import { Assembler } from 'esmodule'

const { CustomEvent, EventTarget } = window
const { getTargetOf } = Assembler
const storage = Symbol()

/**
 * @param {{capture,once,passive,context}|boolean|EventTargetAssembler|*} [options]
 * @param {boolean} [options.capture]
 * @param {boolean} [options.once]
 * @param {boolean} [options.passive]
 * @param {EventTargetAssembler} [options.context]
 * @returns {{capture,once,passive,context}}
 * @private
 */
function getOptions(options) {
    if(options) {
        if(typeof options === 'boolean') {
            return { capture : true }
        }
        if(options instanceof EventTargetAssembler) {
            return { context : options }
        }
        return Object.assign({}, options)
    }
    return {}
}

/**
 * @see https://www.w3.org/TR/dom/#interface-eventtarget
 */
export class EventTargetAssembler extends Assembler {
    /**
     * @param {*} [init]
     */
    create(init) {
        super.create(init)
        this[storage] = { true : {}, false : {} }
    }

    /**
     * @param {Event|string|*} eventOrType
     * @param {CustomEventInit|{}} [eventInitDict]
     * @param {boolean} [eventInitDict.bubbles]
     * @param {boolean} [eventInitDict.cancelable]
     * @param {*} [eventInitDict.detail]
     * @returns {boolean}
     */
    emit(eventOrType, eventInitDict) {
        if(typeof eventOrType === 'string') {
            eventOrType = new CustomEvent(eventOrType, eventInitDict)
        }
        return getTargetOf(this).dispatchEvent(eventOrType)
    }

    /**
     * @param {string} type
     * @param {function} callback
     * @param {{capture,once,passive,context}|boolean|EventTargetAssembler|*} [options]
     * @param {boolean} [options.capture]
     * @param {boolean} [options.once]
     * @param {boolean} [options.passive]
     * @param {EventTargetAssembler} [options.context]
     */
    on(type, callback, options) {
        const { context = this, capture } = options = getOptions(options)
        const handlers = context[storage][Boolean(capture)]
        const map = handlers[type] || (handlers[type] = new Map)
        if(!map.has(callback)) {
            delete options.context
            map.set(callback, callback = callback.bind(context))
            getTargetOf(this).addEventListener(type, callback, options)
        }
    }

    /**
     * @param {string} type
     * @param {function} callback
     * @param {{capture,context}|boolean|EventTargetAssembler|*} [options]
     * @param {boolean} [options.capture]
     * @param {EventTargetAssembler} [options.context]
     */
    un(type, callback, options) {
        const { context = this, capture } = options = getOptions(options)
        const map = context[storage][Boolean(capture)][type]
        if(map && map.has(callback)) {
            delete options.context
            getTargetOf(this).removeEventListener(type, map.get(callback), options)
            map.delete(callback)
        }
    }

    /**
     * @returns {EventTarget}
     * @override
     */
    static create() {
        return new EventTarget
    }

    /**
     * @returns {interface} EventTarget
     * @override
     */
    static get interface() {
        return EventTarget
    }
}
<commit_msg>EventTargetAssembler: get rid of the `create` static method redefinition<commit_after>import { Assembler } from 'esmodule'

const { CustomEvent, EventTarget } = window
const { getTargetOf } = Assembler
const storage = Symbol()

/**
 * @param {{capture,once,passive,context}|boolean|EventTargetAssembler|*} [options]
 * @param {boolean} [options.capture]
 * @param {boolean} [options.once]
 * @param {boolean} [options.passive]
 * @param {EventTargetAssembler} [options.context]
 * @returns {{capture,once,passive,context}}
 * @private
 */
function getOptions(options) {
    if(options) {
        if(options === true) {
            return { capture : true }
        }
        if(options instanceof EventTargetAssembler) {
            return { context : options }
        }
        return Object.assign({}, options)
    }
    return {}
}

/**
 * @see https://www.w3.org/TR/dom/#interface-eventtarget
 */
export class EventTargetAssembler extends Assembler {
    /**
     * @param {*} [init]
     */
    create(init) {
        super.create(init)
        this[storage] = { true : {}, false : {} }
    }

    /**
     * @param {Event|string|*} eventOrType
     * @param {CustomEventInit|{}} [eventInitDict]
     * @param {boolean} [eventInitDict.bubbles]
     * @param {boolean} [eventInitDict.cancelable]
     * @param {*} [eventInitDict.detail]
     * @returns {boolean}
     */
    emit(eventOrType, eventInitDict) {
        if(typeof eventOrType === 'string') {
            eventOrType = new CustomEvent(eventOrType, eventInitDict)
        }
        return getTargetOf(this).dispatchEvent(eventOrType)
    }

    /**
     * @param {string} type
     * @param {function} callback
     * @param {{capture,once,passive,context}|boolean|EventTargetAssembler|*} [options]
     * @param {boolean} [options.capture]
     * @param {boolean} [options.once]
     * @param {boolean} [options.passive]
     * @param {EventTargetAssembler} [options.context]
     */
    on(type, callback, options) {
        const { context = this, capture } = options = getOptions(options)
        const handlers = context[storage][Boolean(capture)]
        const map = handlers[type] || (handlers[type] = new Map)
        if(!map.has(callback)) {
            delete options.context
            map.set(callback, callback = callback.bind(context))
            getTargetOf(this).addEventListener(type, callback, options)
        }
    }

    /**
     * @param {string} type
     * @param {function} callback
     * @param {{capture,context}|boolean|EventTargetAssembler|*} [options]
     * @param {boolean} [options.capture]
     * @param {EventTargetAssembler} [options.context]
     */
    un(type, callback, options) {
        const { context = this, capture } = options = getOptions(options)
        const map = context[storage][Boolean(capture)][type]
        if(map && map.has(callback)) {
            delete options.context
            getTargetOf(this).removeEventListener(type, map.get(callback), options)
            map.delete(callback)
        }
    }

    /**
     * @returns {interface} EventTarget
     * @override
     */
    static get interface() {
        return EventTarget
    }
}
<|endoftext|>


<commit_before>'use strict';

var forEach = require('es5-ext/lib/Object/for-each')
  , ext = require('../_base').ext

ext.maxAge = function (maxAge, conf, options) {
	var cache, mode;

	maxAge = maxAge >>> 0;
	if (!maxAge) {
		return;
	}

	cache = {};
	mode = (options.async && ext.async) ? 'async' : '';
	conf.on('init' + mode, function (id) {
		cache[id] = setTimeout(function () { conf.clear(id); }, maxAge);
	});
	conf.on('purge' + mode, function (id) {
		clearTimeout(cache[id]);
		delete cache[id];
	});

	if (!async) {
		conf.on('purgeall', function (id) {
			forEach(cache, function (id) {
				clearTimeout(id);
			});
			cache = {};
		});
	}
};
<commit_msg>(fix) maxAge: Rely on async events<commit_after>'use strict';

var forEach = require('es5-ext/lib/Object/for-each')
  , ext = require('../_base').ext

ext.maxAge = function (maxAge, conf, options) {
	var cache, async;

	maxAge = maxAge >>> 0;
	if (!maxAge) {
		return;
	}

	cache = {};
	async = options.async && ext.async;
	conf.on('init' + (async ? 'async' : ''), function (id) {
		cache[id] = setTimeout(function () { conf.clear(id); }, maxAge);
	});
	conf.on('purge' + (async ? 'async' : ''), function (id) {
		clearTimeout(cache[id]);
		delete cache[id];
	});

	if (!async) {
		conf.on('purgeall', function (id) {
			forEach(cache, function (id) {
				clearTimeout(id);
			});
			cache = {};
		});
	}
};
<|endoftext|>


<commit_before>var fs = require('fs');
var AWS = require('aws-sdk');
var async = require('async');
var mime = require('mime');
var ogger = require('./ogger');
var path = require('path');
var config = require('config');

AWS.config.update({
  accessKeyId: config.server.aws.accessKeyId,
  secretAccessKey: config.server.aws.secretAccessKey,
});

// TODO: Separate middleware from other logic.
module.exports = function(app, config) {

  var resourcesDir = config.server.resources;

  // Create folders if they don't exist.
  if(!(fs.existsSync(resourcesDir)))            {fs.mkdirSync(resourcesDir);}
  if(!(fs.existsSync(resourcesDir +'/sound')))  {fs.mkdirSync(resourcesDir + '/sound');}
    if(!(fs.existsSync(resourcesDir +'/image')))  {fs.mkdirSync(resourcesDir + '/image');}

  var amazonBaseAddress = "https://storypalette.s3.eu-central-1.amazonaws.com/sound%2F";

  var middleware = {

    // GET resized image: /image/64x64/myimage.jpg
    getImage: function(req, res) {

      // get image dimensions
      var params = req.params[0].split('/');
      var dimensions = params[0].split('x');
      var url;
      console.log(params);
      if (dimensions[1])
        url = 'http://storypalette.imgix.net/' + params[1] + "?fit=clip&h=" + dimensions[0] + "&w=" + dimensions[1];
      else
        url = 'http://storypalette.imgix.net/' + params[0];

      console.log('GET ' + url);

      res.redirect(url);
    },
    // GET sound /sound/mysound.ogg
    // params = {id: 12345, ext: 'mp3'}
    getSound: function(req, res)
    {
      var url = amazonBaseAddress + req.params.id + '.ogg';
      console.log('GET ' + url);
      res.redirect(url);
    },
    // Handle file uploads.
    postFile: function(req, res) {
      console.log('postfile');
      if(req.xhr) {
        var basename = require('path').basename,
            fName = basename(req.header('x-file-name'));

        var ext2type = {
          mp3: 'sound',
          ogg: 'sound',
          jpg: 'image',
          gif: 'image',
          jpeg: 'image',
          png: 'image'
        };

        var extension = fName.substring(fName.lastIndexOf('.')+1);
        var fileId = fName.substr(0, fName.indexOf("."));
        var localPathRaw = resourcesDir + '/' + ext2type[extension]+'/' + fName;
        var localPathOgg = resourcesDir + '/' + ext2type[extension]+'/' + fileId + '.ogg';
        var localPath = localPathRaw;
        var s3PathImage = 'image/' + fName;
        var s3PathSound = 'sound/' + fileId + '.ogg';
        var s3Path;

        if (ext2type[extension] == "image") {
          localPath = localPathRaw;
          s3Path  = s3PathImage;
        }
        else if (ext2type[extension] == "sound") {
          localPath = localPathOgg;
          s3Path = s3PathSound;
        }
          // all sounds are uploaded to AWS S3
          async.waterfall([

            // upload temporarily to web server
            function(callback) {
              var ws = fs.createWriteStream(localPathRaw);
              req.on('data', function(data) {ws.write(data);});
              req.on('end', function(data) {ws.end();
                callback();
              });
            },
            // convert to ogg format
            function(callback) {
              if (ext2type[extension] == "sound") {
                ogger.convert(localPathRaw, localPathOgg, function() {
                  callback();
                });
              }
              else {
                callback();
              }
            },
            // upload to amazon
            function(callback) {
              var body = fs.createReadStream(localPath);
              var s3obj = new AWS.S3({
                signatureVersion: 'v4',
                region: 'eu-central-1',
                params: {
                  Bucket: 'storypalette',
                  Key: s3Path
                }
              });

              s3obj.upload({Body: body}).
              on('httpUploadProgress', function (progress) {
                console.log(progress.loaded + " of " + progress.total + " bytes");

                if (progress.loaded == progress.total) {
                  res.end('finished');
                }
              }).
              send(function(err, data) { console.log(err, data); });

              callback();
            },
            // remove temp file from web server
            function(callback) {
              fs.unlink(localPathRaw);
              fs.unlink(localPathOgg);
              callback();
            }
        ], function(err) {
            if (err) {
              res.status(500).send('upload failure');
            }
        });
      }
    }
  }; // middleware

  return middleware;
};
<commit_msg>Fixed unlink ogg bug<commit_after>var fs = require('fs');
var AWS = require('aws-sdk');
var async = require('async');
var mime = require('mime');
var ogger = require('./ogger');
var path = require('path');
var config = require('config');

AWS.config.update({
  accessKeyId: config.server.aws.accessKeyId,
  secretAccessKey: config.server.aws.secretAccessKey,
});

// TODO: Separate middleware from other logic.
module.exports = function(app, config) {

  var resourcesDir = config.server.resources;

  // Create folders if they don't exist.
  if(!(fs.existsSync(resourcesDir)))            {fs.mkdirSync(resourcesDir);}
  if(!(fs.existsSync(resourcesDir +'/sound')))  {fs.mkdirSync(resourcesDir + '/sound');}
    if(!(fs.existsSync(resourcesDir +'/image')))  {fs.mkdirSync(resourcesDir + '/image');}

  var amazonBaseAddress = "https://storypalette.s3.eu-central-1.amazonaws.com/sound%2F";

  var middleware = {

    // GET resized image: /image/64x64/myimage.jpg
    getImage: function(req, res) {

      // get image dimensions
      var params = req.params[0].split('/');
      var dimensions = params[0].split('x');
      var url;
      console.log(params);
      if (dimensions[1])
        url = 'http://storypalette.imgix.net/' + params[1] + "?fit=clip&h=" + dimensions[0] + "&w=" + dimensions[1];
      else
        url = 'http://storypalette.imgix.net/' + params[0];

      console.log('GET ' + url);

      res.redirect(url);
    },
    // GET sound /sound/mysound.ogg
    // params = {id: 12345, ext: 'mp3'}
    getSound: function(req, res)
    {
      var url = amazonBaseAddress + req.params.id + '.ogg';
      console.log('GET ' + url);
      res.redirect(url);
    },
    // Handle file uploads.
    postFile: function(req, res) {
      console.log('postfile');
      if(req.xhr) {
        var basename = require('path').basename,
            fName = basename(req.header('x-file-name'));

        var ext2type = {
          mp3: 'sound',
          ogg: 'sound',
          jpg: 'image',
          gif: 'image',
          jpeg: 'image',
          png: 'image'
        };

        var extension = fName.substring(fName.lastIndexOf('.')+1);
        var fileId = fName.substr(0, fName.indexOf("."));
        var localPathRaw = resourcesDir + '/' + ext2type[extension]+'/' + fName;
        var localPathOgg = resourcesDir + '/' + ext2type[extension]+'/' + fileId + '.ogg';
        var localPath = localPathRaw;
        var s3PathImage = 'image/' + fName;
        var s3PathSound = 'sound/' + fileId + '.ogg';
        var s3Path;

        if (ext2type[extension] == "image") {
          localPath = localPathRaw;
          s3Path    = s3PathImage;
        } else if (ext2type[extension] == "sound") {
          localPath = localPathOgg;
          s3Path    = s3PathSound;
        }

        // all sounds are uploaded to AWS S3
        async.waterfall([

          // upload temporarily to web server
          function(callback) {
            var ws = fs.createWriteStream(localPathRaw);
            req.on('data', function(data) {ws.write(data);});
            req.on('end', function(data) {ws.end();
              callback();
            });
          },
          function(callback) {
            if (ext2type[extension] == "sound") {
              // convert to ogg format
              ogger.convert(localPathRaw, localPathOgg, function() {
                callback();
              });
            } else {
              callback();
            }
          },
          // upload to amazon
          function(callback) {
            var body = fs.createReadStream(localPath);
            var s3obj = new AWS.S3({
              signatureVersion: 'v4',
              region: 'eu-central-1',
              params: {
                Bucket: 'storypalette',
                Key: s3Path
              }
            });

            s3obj.upload({Body: body}).
            on('httpUploadProgress', function (progress) {
              console.log(progress.loaded + " of " + progress.total + " bytes");

              if (progress.loaded == progress.total) {
                res.end('finished');
              }
            }).
            send(function(err, data) { console.log(err, data); });

            callback();
          },
          // remove temp file from web server
          function(callback) {
            fs.unlink(localPathRaw);

            // TODO improve?
            if (ext2type[extension] == "sound") {
              fs.unlink(localPathOgg);
            }

            callback();
          }
        ], function(err) {
          if (err) {
            res.status(500).send('upload failure');
          }
        });
      }
    }
  }; // middleware

  return middleware;
};
<|endoftext|>


<commit_before>var Flow = require('./flow/flow');
var bunyan = require('bunyan');
var cache = require('./cache');
var socket = require('./socket');

module.exports = function factory (config) {

    return socket.incoming(Flow({
        module: function loadModule (name, callback) {
            try {
                var module = require(config.paths.module + '/' + name);
            } catch (err) {
                return callback(err);
            }

            callback(null, module);
        },
        composition: function (name, callback) {
            try {
                var composition = require(this.config.paths.composition + '/' + name + '.json');
            } catch (err) {
                return callback(err);
            }

            callback(null, composition);
        },
        request: socket.request,
        cache: cache,
        log: bunyan,
        config: config,

        clientComposition: composition,
        clientMarkup: markup,
        // TODO maybe there's a better way to provide a core flow config
        _flow: {
            'C': ['clientComposition'],
            'M': ['clientMarkup']
        }
    }));
};

function markup (stream, options) {

    // TODO just use the stream and send the read file
    if (options.res && options.res.sendFile) {

        // TODO get markup from modules markup path?
        // TODO send markup snipptet from the apps public folder
        res.sendFile(config.paths.markup + '/'/*send markup file*/);
    }
}

function composition (stream, options, name) {

    name = name.toString();

    // handle entrypoint
    if (name === '*') {
        var host = '';//instance = socket.upgradeReq.headers.host.split(':')[0];
        var entrypoints = this.config.entrypoints[stream.session.role ? 'private' : 'public'];

        // TODO maybe entrypoints can have simple routing..
        name = entrypoints[host] || entrypoints['*'];
    }

    if (!name) {
        return stream.end(new Error('Flow.server.composition: No name.'));
    }

    try {
        var composition = require(this.config.paths.composition + '/' + name + '.json');
    } catch (err) {
        return stream.end(err);
    }

    if (!composition.client) {
        return stream.end(new Error('Flow.server.composition: No client config.'));
    }

    composition.client.module = composition.module;

    stream.end(null, JSON.stringify(composition.client));
}
<commit_msg>test data handlers<commit_after>var Flow = require('./flow/flow');
var bunyan = require('bunyan');
var cache = require('./cache');
var socket = require('./socket');

module.exports = function factory (config) {

    return socket.incoming(Flow({
        module: function loadModule (name, callback) {
            try {
                var module = require(config.paths.module + '/' + name);
            } catch (err) {
                return callback(err);
            }

            callback(null, module);
        },
        composition: function (name, callback) {
            try {
                var composition = require(this.config.paths.composition + '/' + name + '.json');
            } catch (err) {
                return callback(err);
            }

            callback(null, composition);
        },
        request: socket.request,
        cache: cache,
        log: bunyan,
        config: config,

        clientComposition: composition,
        clientMarkup: markup,
        // TODO maybe there's a better way to provide a core flow config
        _flow: {
            'C': [':clientComposition'],
            'M': [':clientMarkup']
        }
    }));
};

function markup (stream, options) {

    // TODO just use the stream and send the read file
    if (options.res && options.res.sendFile) {

        // TODO get markup from modules markup path?
        // TODO send markup snipptet from the apps public folder
        res.sendFile(config.paths.markup + '/'/*send markup file*/);
    }
}

function composition (stream, options, name) {

    name = name.toString();

    // handle entrypoint
    if (name === '*') {
        var host = '';//instance = socket.upgradeReq.headers.host.split(':')[0];
        var entrypoints = this.config.entrypoints[stream.session.role ? 'private' : 'public'];

        // TODO maybe entrypoints can have simple routing..
        name = entrypoints[host] || entrypoints['*'];
    }

    if (!name) {
        return stream.end(new Error('Flow.server.composition: No name.'));
    }

    try {
        var composition = require(this.config.paths.composition + '/' + name + '.json');
    } catch (err) {
        return stream.end(err);
    }

    if (!composition.client) {
        return stream.end(new Error('Flow.server.composition: No client config.'));
    }

    composition.client.module = composition.module;

    stream.end(null, JSON.stringify(composition.client));
}
<|endoftext|>


<commit_before>
$.extend(String.prototype, {

  change_resource: function(changes) {
    var item = this.resource();
    $.extend(item, changes);
    Resource.add_or_update(this, item);
  }
});

Demo = {

  delay: function(delay_min, delay_max) {
    if (delay_min == null) delay_min = 1000;
    if (delay_max == null) delay_max = delay_min * 2;
    return delay_min + Math.rand(delay_max - delay_min);
  },

  update_comm: function(person, i, new_val) {
    var comm_parts = person.resource().comm.split(' ');
    comm_parts[i] = new_val;
    return comm_parts.join(' ');
  },

  offer: function(person, op) {
    setTimeout(function(){

      latch_parts = ["latched", Date.unix() + "-" + (Date.unix() + 60*60), op.id, "joe"];
      person.change_resource({
        latch: latch_parts.join(' '),
        sent: op.title,
        comm: Demo.update_comm(person, 2, Date.unix())});
    }, Demo.delay(50, 250));
  },

  // events

  create_rcv_event: function(atype, person, op, changes, json_etc, delay_min, delay_max) {
    setTimeout(function(){
      var evtag = "Annc__" + Ajax.uuid();
      var now = Date.unix();
      changes["comm"] = Demo.update_comm(person, 1, Date.unix());
      if (changes["msg"] == null) changes["msg"] = "create_rcv_event";
      changes["msg_ts"] = Date.unix();
      person.change_resource(changes);
      event(evtag, now, atype, person, op.id, null, op.city_id, person, json_etc);
    }, Demo.delay(delay_min, delay_max));
  },

  // operations

  create_op: function(site, title, atype, body) {
    var optag = "Op__" + Ajax.uuid();
    var city_id = site.resource().city_id;
    op_watch = optag;
    return op(city_id, optag, title, site, This.user.tag, atype, body);
  },

  assign: function(agents, assignment, callback) {
    var op = Demo.create_op(agents[0], "\""+assignment+"\"", 'assignment', assignment);
    callback && callback(op);

    $.each(agents, function(i, agent){
      Demo.offer(agent, op);
      Demo.create_rcv_event('accepted', agent, op,
        {latch: "latched 1-10000 " + op.id + " " + This.user.tag, msg: "ok"}, null, 2000, 8000);
      Demo.create_rcv_event('completed', agent, op, {latch: "unlatched", msg: "done"}, null, 8100);
    });
  },

  invite: function(landmark, title, assignment, callback) {
    var op = Demo.create_op(landmark, "\""+title+"\"", 'assignment invite', title);
    callback && callback(op);

    $.each(Agents.in_city(op.city_id).slice(0, 10), function(i, agent){
      Demo.offer(agent, op);
      Demo.create_rcv_event('accepted', agent.id, op,
        {latch: "latched 1-10000 " + op.id + " " + This.user.tag, msg: "ok"}, null, 2000, 8000);
      Demo.create_rcv_event('completed', agent.id, op, {latch: "unlatched", msg: "done"}, null, 8100);
    });
  },

  question: function(question, agents) {
    console.log(question + " asked of " + agents);
    var op = Demo.create_op(agents[0], "question: " + question, 'assignment question', question);

    $.each(agents, function(i, agent){
      Demo.offer(agent, op);
      answer = "wow, you're a real cool cat";
      answers = agent.resource().answers;
      answers[question] = [answer, Date.unix() + 2000];
      Demo.create_rcv_event('answered', agent, op,
        {latch: "unlatched", msg: answer, answers: answers}, {msg: answer},
        null, 2000, 8000);
    });
  }

};
<commit_msg>Increased demo wait times to 10 secs / 3 mins<commit_after>
$.extend(String.prototype, {

  change_resource: function(changes) {
    var item = this.resource();
    $.extend(item, changes);
    Resource.add_or_update(this, item);
  }
});

Demo = {

  delay: function(delay_min, delay_max) {
    if (delay_min == null) delay_min = 1000;
    if (delay_max == null) delay_max = delay_min * 2;
    return delay_min + Math.rand(delay_max - delay_min);
  },

  update_comm: function(person, i, new_val) {
    var comm_parts = person.resource().comm.split(' ');
    comm_parts[i] = new_val;
    return comm_parts.join(' ');
  },

  offer: function(person, op) {
    setTimeout(function(){

      latch_parts = ["latched", Date.unix() + "-" + (Date.unix() + 60*60), op.id, "joe"];
      person.change_resource({
        latch: latch_parts.join(' '),
        sent: op.title,
        comm: Demo.update_comm(person, 2, Date.unix())});
    }, Demo.delay(50, 250));
  },

  // events

  create_rcv_event: function(atype, person, op, changes, json_etc, delay_min, delay_max) {
    setTimeout(function(){
      var evtag = "Annc__" + Ajax.uuid();
      var now = Date.unix();
      changes["comm"] = Demo.update_comm(person, 1, Date.unix());
      if (changes["msg"] == null) changes["msg"] = "create_rcv_event";
      changes["msg_ts"] = Date.unix();
      person.change_resource(changes);
      event(evtag, now, atype, person, op.id, null, op.city_id, person, json_etc);
    }, Demo.delay(delay_min, delay_max));
  },

  // operations

  create_op: function(site, title, atype, body) {
    var optag = "Op__" + Ajax.uuid();
    var city_id = site.resource().city_id;
    op_watch = optag;
    return op(city_id, optag, title, site, This.user.tag, atype, body);
  },

  assign: function(agents, assignment, callback) {
    var op = Demo.create_op(agents[0], "\""+assignment+"\"", 'assignment', assignment);
    callback && callback(op);

    $.each(agents, function(i, agent){
      Demo.offer(agent, op);
      Demo.create_rcv_event('accepted', agent, op,
        {latch: "latched 1-10000 " + op.id + " " + This.user.tag, msg: "ok"}, null, 10*1000);
      Demo.create_rcv_event('completed', agent, op, {latch: "unlatched", msg: "done"}, null, 3*60*1000);
    });
  },

  invite: function(landmark, title, assignment, callback) {
    var op = Demo.create_op(landmark, "\""+title+"\"", 'assignment invite', title);
    callback && callback(op);

    $.each(Agents.in_city(op.city_id).slice(0, 10), function(i, agent){
      Demo.offer(agent, op);
      Demo.create_rcv_event('accepted', agent.id, op,
        {latch: "latched 1-10000 " + op.id + " " + This.user.tag, msg: "ok"}, null, 10*1000);
      Demo.create_rcv_event('completed', agent.id, op, {latch: "unlatched", msg: "done"}, null, 3*60*1000);
    });
  },

  question: function(question, agents) {
    console.log(question + " asked of " + agents);
    var op = Demo.create_op(agents[0], "question: " + question, 'assignment question', question);

    $.each(agents, function(i, agent){
      Demo.offer(agent, op);
      answer = "I don't understand your question: " + question;
      answers = agent.resource().answers;
      answers[question] = [answer, Date.unix() + 3*60*1000];
      Demo.create_rcv_event('answered', agent, op,
        {latch: "unlatched", msg: answer, answers: answers}, {msg: answer},
        null, 3*60*1000);
    });
  }

};
<|endoftext|>


<commit_before>/**
 * git-control
 * Copyright Aboubakr GASMI <g13013@gmail.com>
 * License: MIT
 */

'use strict';

//TODO read .git file on submodules
//TODO implement exec-sync

var pio = require('promised-io/promise'),
    gitConfig = require('./utils/git-config-parser.js'),
    path = require('path'),
    cp = require('child_process'),
    exec = cp.exec,
    cwd = process.cwd(),
    branchRe = /(\*)? +([^\n]+)[\n]?/g,
    tagsRe = /[\n]?([^\n]+)[\n]?/g,
    stagedRe = /(?:^|\n)[MADRC]\s+([^\n]+)/g,
    untrackedRe = /\?\?\s+([^\n]+)/g,
    modifiedRe = /(?:^|\n)\s[MADRCU]\s([^\n]+)/g,
    subRe = /(?:^|\n)(.+) (.+) \((.+)\)/g,
    ps = function (command, options) {
      options = options || {};
      var proc, cmd, opt, resolved,
          deferred = pio.Deferred();
      //TODO check command type
      if (typeof command === 'string') {
        cmd = command;
      } else {
        cmd = command.cmd;
        opt = command.opt;
      }

      proc = exec(cmd, opt, function (err, stdout, stderr) {
        if (err) {
          if (options.verbose) {
            console.log('Failed.\n');
          }
          if (resolved) {
            return;
          }
          if (options.ignore) {
            deferred.resolve(false);
          } else {
            deferred.reject(stderr);
          }
        } else {
          if (options.verbose) {
            console.log('Ok.\n');
          }
          deferred.resolve(stdout);
        }
        resolved = true;
      });

      if (options.timeout && options.timeout > 0) {
        setTimeout(function () {
          proc.kill();
          if (resolved) {
            return;
          }
          resolved = true;
          if (options.ignore) {
            deferred.resolve(false);
            return;
          }
          deferred.reject('Aborted due to timeout!');
        }, options.timeout * 1000);
      }

      if (options.verbose) {
        proc.stderr.on('data', function (data) {
          console.warn(data.replace(/(^|\n)([^\n]+)/g, '$1\t\t$2'));
        });
      }
      return deferred;
    },
    collect = function (re, str) {//collects matching regex values
      var matches = [],
        match;
      if (!re.global) {
        match = re.exec(str);
        return match && match[1];
      }
      while ((match = re.exec(str)) !== null) {
        matches.push(match[1]);
      }
      return matches;
    },
    execSequence = function (list, scope) {
      var seq = list.map(function (name) {
        var args = [];
        if (name instanceof Array) {
          args = name.slice(1);
          name = name[0];
        } else {
          args = [];
        }
        return function () {
          return scope[name].apply(scope, args);
        };
      }, scope);
      return pio.seq(seq);
    };
var Git = function (options) {
  options = options || {};

  if (typeof options === 'string') {
    options = {path: options};
  }

  this.path = options.path || '.';
  this.workTree = options.workTree || options.path || this.workTree;
  this.gitDir = options.gitDir || (options.path && (options.path + '/.git')) || this.gitDir;
  this.config = gitConfig.parse(this.gitDir + '/config', true);
  this.verbose = options.verbose || false;
  this.safeMode = options.safeMode || true;
  this.info = null;
  this.getInfo.call(this, true);
  return this;
};

function copyState(dest, source) {
  var key;
  for (key in source) {
    if (source.hasOwnProperty(key)) {
      dest[key] = source[key];
    }
  }
}

Git.prototype = {
  path: cwd,
  gitDir: cwd + '/.git',
  workTree: cwd,
  parent: null,
  isSubmodule: false,
  defaultTimeout: null,
  saved: false,
  exec: function (command, ignore, timeout) {
    if (this.verbose) {
      console.log('Executing Git command `' + command + '` at directory : ' + this.path);
      console.log('git-dir: ' + this.gitDir);
      console.log('work-tree: ' + this.workTree);
    }
    var paths = (this.path) ? ('--git-dir="' + path.resolve(this.gitDir) +  '" --work-tree="' + path.resolve(this.workTree) + '" '): '';
    command  = 'git ' + paths + command;
    return ps({
      cmd: command,
      opt: {cwd: path.resolve(this.path)}
    }, {
      verbose: this.verbose,
      ignore: ignore,
      timeout: timeout || this.defaultTimeout
    });
  },
  getInfo: function (fetch) {
    var info = pio.Deferred(),
        infoSeq = ['log', 'branch', 'status', 'tag', 'submodule'];

    this.info = info; //state is a deferred object

    fetch = (fetch !== false) ? true : false;

    if (fetch === true) {
      infoSeq.splice(1, 0, 'fetch');
    }

    copyState(info, {
      ahead: null,
      behind: null,
      currentRev: null,
      currentBranch: null,
      isClean: null,
      staged: null,
      isDetached: null,
      branches: null,
      tags: null,
      submodules: null,
      stagedFiles: null,
      modifiedFiles: null,
      untrackedFiles: null
    });

    execSequence(infoSeq, this).then(function () {
      info.resolve(info);
    }, function (reason) {
      var err = (typeof reason === 'string') ? reason : (reason && reason.message);
      info.reject('Error while getting repository info: ' + err);
    });

    return info;
  },
  log: function (command) {
    if (command) {
      return this.exec('log ' + command);
    }
    //Default action updates state
    var info = this.info;
    return this.exec('log -n 1 --pretty=format:"%H" | cat').then(function (out) {
      info.sha = out;
      info.currentRev = out.substr(0, 7);
    });
  },
  status: function (command) {
    if (command) {
      return this.exec('status ' + command);
    }
    var info = this.info;
    return this.exec('status -s -b').then(function (out) {
      out.replace(/(ahead|behind) ([0-9]*)[\]\,]/, function (match, direction, nbr) {
        info[direction] = Number(nbr);
      });
      info.behind = info.behind || 0;
      info.ahead = info.ahead || 0;
      info.stagedFiles = collect(stagedRe, out);
      info.modifiedFiles = collect(modifiedRe, out).concat(info.stagedFiles);
      info.untrackedFiles = collect(untrackedRe, out);
      info.staged = !!info.stagedFiles.length;
      info.modified = !!info.modifiedFiles.length;
      info.isClean = !info.modifiedFiles.length;
    });
  },
  tag: function (command) {
    var info,
        args = ['exec'];
    if (command) {
      args.push('tag ' + command);
      return execSequence([args, 'tag'], this);
    }
    info = this.info;
    return this.exec('tag').then(function (tagOutput) {
      info.tags = collect(tagsRe, tagOutput);
    });
  },
  submodule: function (command) {
    var args, sub, info,
        self = this;
    if (command) {
      args = ['exec', 'submodule ' + command];
      return execSequence([args, 'submodule'], this);
    }

    info = this.info;

    if (info.submodules) {
      /*jshint -W089*/
      for (sub in info.submodules) {
        delete info.submodule[sub];
      }
    }

    return this.exec('submodule status').then(function (out) {
      var states = [];
      info.submodules = {};
      out.replace(subRe, function (match, sha, subPath) {
        var subName = subPath.split('/').pop(),
          repo = new Git({
            path: subPath,
            parent: self,
            gitDir: self.gitDir + '/modules/' + subPath,
            isSubmodule: true,
            verbose: self.verbose,
            defaultTimeout: self.defaultTimeout,
            safeMode: self.safeMode
          });
        info.submodules[subName] = {
          path: subPath,
          sha: sha,
          repo: repo
        };
        self.submodule[subName] = repo;
        states.push(repo.info);
      });
      return pio.all(states);
    });
  },
  branch: function (command) {
    var args = ['branch'],
        info;
    if (command) {
      args.push('branch ' + command);
      return execSequence([args, 'log', 'branch'], this);
    }
    info = this.info;
    return this.exec('branch').then(function (data) {
      var branches = [];
      data.replace(branchRe, function (match, current, branch) {
        var detached;
        if (current) {
          detached = /\(detached from ([^\)]+)\)/.exec(branch);
          info.isDetached = !!detached;
          if (info.isDetached) {
            info.currentBranch = detached[1];
          } else {
            info.currentBranch = branch;
            branches.push(branch);
          }
          return;
        }
        branches.push(branch);
      });
      info.branches = branches;
    });
  },
  fetch: function (all, includeTags, ignore, timeout) {
    var args;
    timeout = timeout || this.defaultTimeout || 10;
    if (arguments.length) {
      all = (all) ? ' --all' : '';
      includeTags = (includeTags) ? ' --tags' : '';
      ignore = (ignore !== false) ? true : false;
      args = ['exec', 'fetch' + all + includeTags, ignore, timeout];
      return execSequence([args, 'tag'], this);
    }
    args = ['exec', 'fetch --tags', true, timeout];
    return execSequence([args], this);
  },
  checkout: function (rev, force) {
    var args,
      isTagVersion = /^tags\//.test(rev),
      tag = isTagVersion && rev.replace(/^tags\//, '');
    force = ((force) ? ' --force' : '');
    if ((isTagVersion && this.info.currentBranch !== tag) || this.info.currentBranch !== rev) {
      if (force || !this.safeMode || this.info.isClean) {
        args = ['exec', 'checkout ' + rev + force, false];
        return execSequence([args, 'log', 'branch'], this);
      }
      pio.Deferred().reject('Can\'t checkout revision  `' + rev + '` in the repository at path `' +
               (this.path || this.workTree) +
               '`, repository is not clean, \n call with `force` or set the `safeMode` option.');
    }
    return this.info;
  },
  pull: function (rebase, force) {
    var args;
    force = ((force) ? ' --force' : '');
    rebase = (rebase === true) ? ' --rebase' : '';
    if (force || !this.safeMode || (!this.info.ahead && !this.info.isDetached && this.info.isClean)) {
      args = ['exec', 'pull' + rebase + force, false, true];
      return execSequence([args, 'log'], this);
    } else {
      return pio.Deferred().reject('Can\'t pull changes in the repository at path `' +
                (this.path || this.workTree) +
                '`, repository is not clean or is detached, \n call with `force` or set the `safeMode` option.');
    }
  },
  add: function (files) {
    var args = ['exec'];
    if (files instanceof Array) {
      files = files.map(function (file) {
        return '"' + file + '"';
      }).join(' ');
    }
    args.push('add ' + files);
    return execSequence([args, 'status'], this);
  },
  commit: function (message) {
    var args = ['exec', 'commit -m "' + message + '" --no-verify', false];
    return execSequence([args, 'log'], this);
  },
  stash: function (command, message, opt) {
    if (arguments.length === 1 && typeof command !== 'string') {
      opt = command;
      command = 'save';
      message = '';
    } else if (arguments.length === 2 && typeof message !== 'string') {
      opt = message;
      message = '';
    } else {
      command = command || 'save';
      message = message || '';
    }
    opt = opt || {};
    var untracked = (opt.includeUntracked === true) ? '-u' : '',
        keepIdx = (opt.keepIndex === true) ? '--keep-index' : '',
        cmd = ['stash', command, keepIdx, untracked, message],
        args = ['exec', cmd.join(' '), false];
    return execSequence([args], this);
  },
  saveRestore: function () {
    var self = this;
    if (!self.saved) {
      return self.stash('save', {includeUntracked: true}).then(function () {
        self.saved = true;
      });
    }
    return execSequence([['stash', 'pop'], ['stash', 'drop']], this).then(function () {
      self.saved = false;
    });
  },
  printInfo: function (full, force) {
    var str, output = {};
    if (force) {
      this.getInfo(true);
    }

    return this.info.then(function (info) {
      var key, sub;
      /*jshint -W069 */
      output['Unpushed'] = info.ahead;
      output['Commits behind'] = info.behind;
      output['Current revision'] = info.currentRev;
      output['Rev sha'] = info.sha;
      output['Current pointer/branch'] = info.currentBranch;
      output['Clean'] = info.isClean;
      output['Staged'] = info.staged;
      output['Detached'] = info.isDetached;
      output['Staged files'] = info.stagedFiles;
      output['Modified files'] = info.modifiedFiles;
      output['Untracked files'] = info.untrackedFiles;
      output['Branches'] = info.branches;
      output['Tags'] = info.tags;
      if (full) {
        output['Sub modules'] = info.submodules;
      } else {
        output['Sub modules'] = sub = {};
        /*jshint -W089 */
        for (key in info.submodules) {
          sub[key] = {};
          sub[key]['path'] = info.submodules[key].repo.path;
          sub[key]['currentRev'] = info.submodules[key].repo.info.currentRev;
        }
      }
      str = JSON.stringify(output, null, 2);
      str = str.replace(/(^{|}$)/g, '');
      str = str.replace(/"/gm, '');
      console.log(str);
    });
  }
};

module.exports = {
  exec: function (command) {
    return Git.prototype.exec(command);
  },
  repo: function (path) {
    return new Git(path);
  }
};
<commit_msg>return promise only when there's seq<commit_after>/**
 * git-control
 * Copyright Aboubakr GASMI <g13013@gmail.com>
 * License: MIT
 */

'use strict';

//TODO read .git file on submodules
//TODO implement exec-sync

var pio = require('promised-io/promise'),
    gitConfig = require('./utils/git-config-parser.js'),
    path = require('path'),
    cp = require('child_process'),
    exec = cp.exec,
    cwd = process.cwd(),
    branchRe = /(\*)? +([^\n]+)[\n]?/g,
    tagsRe = /[\n]?([^\n]+)[\n]?/g,
    stagedRe = /(?:^|\n)[MADRC]\s+([^\n]+)/g,
    untrackedRe = /\?\?\s+([^\n]+)/g,
    modifiedRe = /(?:^|\n)\s[MADRCU]\s([^\n]+)/g,
    subRe = /(?:^|\n)(.+) (.+) \((.+)\)/g,
    ps = function (command, options) {
      options = options || {};
      var proc, cmd, opt, resolved,
          deferred = pio.Deferred();
      //TODO check command type
      if (typeof command === 'string') {
        cmd = command;
      } else {
        cmd = command.cmd;
        opt = command.opt;
      }

      proc = exec(cmd, opt, function (err, stdout, stderr) {
        if (err) {
          if (options.verbose) {
            console.log('Failed.\n');
          }
          if (resolved) {
            return;
          }
          if (options.ignore) {
            deferred.resolve(false);
          } else {
            deferred.reject(stderr);
          }
        } else {
          if (options.verbose) {
            console.log('Ok.\n');
          }
          deferred.resolve(stdout);
        }
        resolved = true;
      });

      if (options.timeout && options.timeout > 0) {
        setTimeout(function () {
          proc.kill();
          if (resolved) {
            return;
          }
          resolved = true;
          if (options.ignore) {
            deferred.resolve(false);
            return;
          }
          deferred.reject('Aborted due to timeout!');
        }, options.timeout * 1000);
      }

      if (options.verbose) {
        proc.stderr.on('data', function (data) {
          console.warn(data.replace(/(^|\n)([^\n]+)/g, '$1\t\t$2'));
        });
      }
      return deferred;
    },
    collect = function (re, str) {//collects matching regex values
      var matches = [],
        match;
      if (!re.global) {
        match = re.exec(str);
        return match && match[1];
      }
      while ((match = re.exec(str)) !== null) {
        matches.push(match[1]);
      }
      return matches;
    },
    execSequence = function (list, scope) {
      var seq = list.map(function (name) {
        var args = [];
        if (name instanceof Array) {
          args = name.slice(1);
          name = name[0];
        } else {
          args = [];
        }
        return function () {
          return scope[name].apply(scope, args);
        };
      }, scope);
      return pio.seq(seq);
    };
var Git = function (options) {
  options = options || {};

  if (typeof options === 'string') {
    options = {path: options};
  }

  this.path = options.path || '.';
  this.workTree = options.workTree || options.path || this.workTree;
  this.gitDir = options.gitDir || (options.path && (options.path + '/.git')) || this.gitDir;
  this.config = gitConfig.parse(this.gitDir + '/config', true);
  this.verbose = options.verbose || false;
  this.safeMode = options.safeMode || true;
  this.info = null;
  this.getInfo.call(this, true);
  return this;
};

function copyState(dest, source) {
  var key;
  for (key in source) {
    if (source.hasOwnProperty(key)) {
      dest[key] = source[key];
    }
  }
}

Git.prototype = {
  path: cwd,
  gitDir: cwd + '/.git',
  workTree: cwd,
  parent: null,
  isSubmodule: false,
  defaultTimeout: null,
  saved: false,
  exec: function (command, ignore, timeout) {
    if (this.verbose) {
      console.log('Executing Git command `' + command + '` at directory : ' + this.path);
      console.log('git-dir: ' + this.gitDir);
      console.log('work-tree: ' + this.workTree);
    }
    var paths = (this.path) ? ('--git-dir="' + path.resolve(this.gitDir) +  '" --work-tree="' + path.resolve(this.workTree) + '" '): '';
    command  = 'git ' + paths + command;
    return ps({
      cmd: command,
      opt: {cwd: path.resolve(this.path)}
    }, {
      verbose: this.verbose,
      ignore: ignore,
      timeout: timeout || this.defaultTimeout
    });
  },
  getInfo: function (fetch) {
    var info = pio.Deferred(),
        infoSeq = ['log', 'branch', 'status', 'tag', 'submodule'];

    this.info = info; //state is a deferred object

    fetch = (fetch !== false) ? true : false;

    if (fetch === true) {
      infoSeq.splice(1, 0, 'fetch');
    }

    copyState(info, {
      ahead: null,
      behind: null,
      currentRev: null,
      currentBranch: null,
      isClean: null,
      staged: null,
      isDetached: null,
      branches: null,
      tags: null,
      submodules: null,
      stagedFiles: null,
      modifiedFiles: null,
      untrackedFiles: null
    });

    execSequence(infoSeq, this).then(function () {
      info.resolve(info);
    }, function (reason) {
      var err = (typeof reason === 'string') ? reason : (reason && reason.message);
      info.reject('Error while getting repository info: ' + err);
    });

    return info;
  },
  log: function (command) {
    if (command) {
      return this.exec('log ' + command);
    }
    //Default action updates state
    var info = this.info;
    return this.exec('log -n 1 --pretty=format:"%H" | cat').then(function (out) {
      info.sha = out;
      info.currentRev = out.substr(0, 7);
    });
  },
  status: function (command) {
    if (command) {
      return this.exec('status ' + command);
    }
    var info = this.info;
    return this.exec('status -s -b').then(function (out) {
      out.replace(/(ahead|behind) ([0-9]*)[\]\,]/, function (match, direction, nbr) {
        info[direction] = Number(nbr);
      });
      info.behind = info.behind || 0;
      info.ahead = info.ahead || 0;
      info.stagedFiles = collect(stagedRe, out);
      info.modifiedFiles = collect(modifiedRe, out).concat(info.stagedFiles);
      info.untrackedFiles = collect(untrackedRe, out);
      info.staged = !!info.stagedFiles.length;
      info.modified = !!info.modifiedFiles.length;
      info.isClean = !info.modifiedFiles.length;
    });
  },
  tag: function (command) {
    var info,
        args = ['exec'];
    if (command) {
      args.push('tag ' + command);
      return execSequence([args, 'tag'], this);
    }
    info = this.info;
    return this.exec('tag').then(function (tagOutput) {
      info.tags = collect(tagsRe, tagOutput);
    });
  },
  submodule: function (command) {
    var args, sub, info,
        self = this;
    if (command) {
      args = ['exec', 'submodule ' + command];
      return execSequence([args, 'submodule'], this);
    }

    info = this.info;

    if (info.submodules) {
      /*jshint -W089*/
      for (sub in info.submodules) {
        delete info.submodule[sub];
      }
    }

    return this.exec('submodule status').then(function (out) {
      var states = [];
      info.submodules = {};
      out.replace(subRe, function (match, sha, subPath) {
        var subName = subPath.split('/').pop(),
          repo = new Git({
            path: subPath,
            parent: self,
            gitDir: self.gitDir + '/modules/' + subPath,
            isSubmodule: true,
            verbose: self.verbose,
            defaultTimeout: self.defaultTimeout,
            safeMode: self.safeMode
          });
        info.submodules[subName] = {
          path: subPath,
          sha: sha,
          repo: repo
        };
        self.submodule[subName] = repo;
        states.push(repo.info);
      });
      if (states.length > 0) {
        return pio.all(states);
      }
    });
  },
  branch: function (command) {
    var args = ['branch'],
        info;
    if (command) {
      args.push('branch ' + command);
      return execSequence([args, 'log', 'branch'], this);
    }
    info = this.info;
    return this.exec('branch').then(function (data) {
      var branches = [];
      data.replace(branchRe, function (match, current, branch) {
        var detached;
        if (current) {
          detached = /\(detached from ([^\)]+)\)/.exec(branch);
          info.isDetached = !!detached;
          if (info.isDetached) {
            info.currentBranch = detached[1];
          } else {
            info.currentBranch = branch;
            branches.push(branch);
          }
          return;
        }
        branches.push(branch);
      });
      info.branches = branches;
    });
  },
  fetch: function (all, includeTags, ignore, timeout) {
    var args;
    timeout = timeout || this.defaultTimeout || 10;
    if (arguments.length) {
      all = (all) ? ' --all' : '';
      includeTags = (includeTags) ? ' --tags' : '';
      ignore = (ignore !== false) ? true : false;
      args = ['exec', 'fetch' + all + includeTags, ignore, timeout];
      return execSequence([args, 'tag'], this);
    }
    args = ['exec', 'fetch --tags', true, timeout];
    return execSequence([args], this);
  },
  checkout: function (rev, force) {
    var args,
      isTagVersion = /^tags\//.test(rev),
      tag = isTagVersion && rev.replace(/^tags\//, '');
    force = ((force) ? ' --force' : '');
    if ((isTagVersion && this.info.currentBranch !== tag) || this.info.currentBranch !== rev) {
      if (force || !this.safeMode || this.info.isClean) {
        args = ['exec', 'checkout ' + rev + force, false];
        return execSequence([args, 'log', 'branch'], this);
      }
      pio.Deferred().reject('Can\'t checkout revision  `' + rev + '` in the repository at path `' +
               (this.path || this.workTree) +
               '`, repository is not clean, \n call with `force` or set the `safeMode` option.');
    }
    return this.info;
  },
  pull: function (rebase, force) {
    var args;
    force = ((force) ? ' --force' : '');
    rebase = (rebase === true) ? ' --rebase' : '';
    if (force || !this.safeMode || (!this.info.ahead && !this.info.isDetached && this.info.isClean)) {
      args = ['exec', 'pull' + rebase + force, false, true];
      return execSequence([args, 'log'], this);
    } else {
      return pio.Deferred().reject('Can\'t pull changes in the repository at path `' +
                (this.path || this.workTree) +
                '`, repository is not clean or is detached, \n call with `force` or set the `safeMode` option.');
    }
  },
  add: function (files) {
    var args = ['exec'];
    if (files instanceof Array) {
      files = files.map(function (file) {
        return '"' + file + '"';
      }).join(' ');
    }
    args.push('add ' + files);
    return execSequence([args, 'status'], this);
  },
  commit: function (message) {
    var args = ['exec', 'commit -m "' + message + '" --no-verify', false];
    return execSequence([args, 'log'], this);
  },
  stash: function (command, message, opt) {
    if (arguments.length === 1 && typeof command !== 'string') {
      opt = command;
      command = 'save';
      message = '';
    } else if (arguments.length === 2 && typeof message !== 'string') {
      opt = message;
      message = '';
    } else {
      command = command || 'save';
      message = message || '';
    }
    opt = opt || {};
    var untracked = (opt.includeUntracked === true) ? '-u' : '',
        keepIdx = (opt.keepIndex === true) ? '--keep-index' : '',
        cmd = ['stash', command, keepIdx, untracked, message],
        args = ['exec', cmd.join(' '), false];
    return execSequence([args], this);
  },
  saveRestore: function () {
    var self = this;
    if (!self.saved) {
      return self.stash('save', {includeUntracked: true}).then(function () {
        self.saved = true;
      });
    }
    return execSequence([['stash', 'pop'], ['stash', 'drop']], this).then(function () {
      self.saved = false;
    });
  },
  printInfo: function (full, force) {
    var str, output = {};
    if (force) {
      this.getInfo(true);
    }

    return this.info.then(function (info) {
      var key, sub;
      /*jshint -W069 */
      output['Unpushed'] = info.ahead;
      output['Commits behind'] = info.behind;
      output['Current revision'] = info.currentRev;
      output['Rev sha'] = info.sha;
      output['Current pointer/branch'] = info.currentBranch;
      output['Clean'] = info.isClean;
      output['Staged'] = info.staged;
      output['Detached'] = info.isDetached;
      output['Staged files'] = info.stagedFiles;
      output['Modified files'] = info.modifiedFiles;
      output['Untracked files'] = info.untrackedFiles;
      output['Branches'] = info.branches;
      output['Tags'] = info.tags;
      if (full) {
        output['Sub modules'] = info.submodules;
      } else {
        output['Sub modules'] = sub = {};
        /*jshint -W089 */
        for (key in info.submodules) {
          sub[key] = {};
          sub[key]['path'] = info.submodules[key].repo.path;
          sub[key]['currentRev'] = info.submodules[key].repo.info.currentRev;
        }
      }
      str = JSON.stringify(output, null, 2);
      str = str.replace(/(^{|}$)/g, '');
      str = str.replace(/"/gm, '');
      console.log(str);
    });
  }
};

module.exports = {
  exec: function (command) {
    return Git.prototype.exec(command);
  },
  repo: function (path) {
    return new Git(path);
  }
};
<|endoftext|>


<commit_before>/** @babel */

import {shell} from 'electron'
import {Range} from 'atom'
import {parse as parseURL} from 'url'
import path from 'path'

export default class GitHubFile {
  // Public
  static fromPath (filePath) {
    return new GitHubFile(filePath)
  }

  constructor (filePath) {
    this.filePath = filePath
    const [rootDir] = atom.project.relativizePath(this.filePath)

    if (rootDir != null) {
      const rootDirIndex = atom.project.getPaths().indexOf(rootDir)
      this.repo = atom.project.getRepositories()[rootDirIndex]
    }
  }

  // Public
  open (lineRange) {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.blobURL() + this.getLineRangeSuffix(lineRange))
    }
  }

  // Public
  openOnMaster (lineRange) {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.blobURLForMaster() + this.getLineRangeSuffix(lineRange))
    }
  }

  // Public
  blame (lineRange) {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.blameURL() + this.getLineRangeSuffix(lineRange))
    }
  }

  history () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.historyURL())
    }
  }

  copyURL (lineRange) {
    if (this.validateRepo()) {
      atom.clipboard.write(this.shaURL() + this.getLineRangeSuffix(lineRange))
    }
  }

  openBranchCompare () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.branchCompareURL())
    }
  }

  openIssues () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.issuesURL())
    }
  }

  openPullRequests () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.pullRequestsURL())
    }
  }

  openRepository () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.githubRepoURL())
    }
  }

  getLineRangeSuffix (lineRange) {
    if (lineRange && !this.isGitHubWikiURL(this.githubRepoURL()) && atom.config.get('open-on-github.includeLineNumbersInUrls')) {
      lineRange = Range.fromObject(lineRange)
      const startRow = lineRange.start.row + 1
      const endRow = lineRange.end.row + 1

      if (startRow === endRow) {
        if (this.isGistURL(this.githubRepoURL())) {
          return `-L${startRow}`
        } else {
          return `#L${startRow}`
        }
      } else {
        if (this.isGistURL(this.githubRepoURL())) {
          return `-L${startRow}-L${endRow}`
        } else {
          return `#L${startRow}-L${endRow}`
        }
      }
    } else {
      return ''
    }
  }

  // Internal
  validateRepo () {
    if (!this.repo) {
      atom.notifications.addWarning(`No repository found for path: ${this.filePath}.`)
      return false
    } else if (!this.gitURL()) {
      atom.notifications.addWarning(`No URL defined for remote: ${this.remoteName()}`)
      return false
    } else if (!this.githubRepoURL()) {
      atom.notifications.addWarning(`Remote URL is not hosted on GitHub: ${this.gitURL()}`)
      return false
    }
    return true
  }

  // Internal
  openURLInBrowser (url) {
    shell.openExternal(url)
  }

  // Internal
  blobURL () {
    const gitHubRepoURL = this.githubRepoURL()
    const repoRelativePath = this.repoRelativePath()

    if (this.isGitHubWikiURL(gitHubRepoURL)) {
      return `${gitHubRepoURL.slice(0, -5)}/wiki/${this.extractFileName(repoRelativePath)}`
    } else if (this.isGistURL(gitHubRepoURL)) {
      return `${gitHubRepoURL}#file-${this.encodeSegments(repoRelativePath.replace(/\./g, '-'))}`
    } else {
      return `${gitHubRepoURL}/blob/${this.remoteBranchName()}/${this.encodeSegments(repoRelativePath)}`
    }
  }

  // Internal
  blobURLForMaster () {
    const gitHubRepoURL = this.githubRepoURL()

    if (this.isGitHubWikiURL(gitHubRepoURL) || this.isGistURL(gitHubRepoURL)) {
      return this.blobURL() // Gists do not have branches
    } else {
      return `${gitHubRepoURL}/blob/master/${this.encodeSegments(this.repoRelativePath())}`
    }
  }

  // Internal
  shaURL () {
    const gitHubRepoURL = this.githubRepoURL()
    const encodedSHA = this.encodeSegments(this.sha())
    const repoRelativePath = this.repoRelativePath()

    if (this.isGitHubWikiURL(gitHubRepoURL)) {
      return `${gitHubRepoURL.slice(0, -5)}/wiki/${this.extractFileName(repoRelativePath)}/${encodedSHA}`
    } else if (this.isGistURL(gitHubRepoURL)) {
      return `${gitHubRepoURL}/${encodedSHA}#file-${this.encodeSegments(repoRelativePath.replace(/\./g, '-'))}`
    } else {
      return `${gitHubRepoURL}/blob/${encodedSHA}/${this.encodeSegments(repoRelativePath)}`
    }
  }

  // Internal
  blameURL () {
    return `${this.githubRepoURL()}/blame/${this.remoteBranchName()}/${this.encodeSegments(this.repoRelativePath())}`
  }

  // Internal
  historyURL () {
    const gitHubRepoURL = this.githubRepoURL()

    if (this.isGistURL(gitHubRepoURL)) {
      return `${gitHubRepoURL}/revisions`
    } else {
      return `${gitHubRepoURL}/commits/${this.remoteBranchName()}/${this.encodeSegments(this.repoRelativePath())}`
    }
  }

  // Internal
  issuesURL () {
    return `${this.githubRepoURL()}/issues`
  }

  // Internal
  pullRequestsURL () {
    return `${this.githubRepoURL()}/pulls`
  }

  // Internal
  branchCompareURL () {
    return `${this.githubRepoURL()}/compare/${this.encodeSegments(this.branchName())}`
  }

  encodeSegments (segments = '') {
    return segments.split('/').map(segment => encodeURIComponent(segment)).join('/')
  }

  // Internal
  extractFileName (relativePath = '') {
    return path.parse(relativePath).name
  }

  // Internal
  gitURL () {
    const remoteName = this.remoteName()
    if (remoteName != null) {
      return this.repo.getConfigValue(`remote.${remoteName}.url`, this.filePath)
    } else {
      return this.repo.getConfigValue(`remote.origin.url`, this.filePath)
    }
  }

  // Internal
  githubRepoURL () {
    let url = this.gitURL()

    if (url.match(/git@[^:]+:/)) {
      url = url.replace(/^git@([^:]+):(.+)$/, (match, host, repoPath) => {
        repoPath = repoPath.replace(/^\/+/, '')
        return `http://${host}/${repoPath}`
      })
    } else if (url.match(/ssh:\/\/git@([^/]+)\//)) {
      url = `http://${url.substring(10)}`
    } else if (url.match(/^git:\/\/[^/]+\//)) {
      url = `http${url.substring(3)}`
    }

    // Remove trailing .git and trailing slashes
    url = url.replace(/\.git$/, '').replace(/\/+$/, '')

    if (!this.isBitbucketURL(url)) {
      return url
    }
  }

  isGistURL (url) {
    try {
      const {host} = parseURL(url)

      return host === 'gist.github.com'
    } finally {}
  }

  isGitHubWikiURL (url) {
    return /\.wiki$/.test(url)
  }

  isBitbucketURL (url) {
    if (url.startsWith('git@bitbucket.org')) {
      return true
    }

    try {
      const {host} = parseURL(url)

      return host === 'bitbucket.org'
    } finally {}
  }

  // Internal
  repoRelativePath () {
    return this.repo.getRepo(this.filePath).relativize(this.filePath)
  }

  // Internal
  remoteName () {
    const gitConfigRemote = this.repo.getConfigValue('atom.open-on-github.remote', this.filePath)

    if (gitConfigRemote) {
      return gitConfigRemote
    }

    const shortBranch = this.repo.getShortHead(this.filePath)

    if (!shortBranch) {
      return null
    }

    const branchRemote = this.repo.getConfigValue(`branch.${shortBranch}.remote`, this.filePath)

    if (branchRemote && branchRemote.length > 0) {
      return branchRemote
    }

    return null
  }

  // Internal
  sha () {
    return this.repo.getReferenceTarget('HEAD', this.filePath)
  }

  // Internal
  branchName () {
    const shortBranch = this.repo.getShortHead(this.filePath)

    if (!shortBranch) {
      return null
    }

    const branchMerge = this.repo.getConfigValue(`branch.${shortBranch}.merge`, this.filePath)
    if (!(branchMerge && branchMerge.length > 11)) {
      return shortBranch
    }

    if (branchMerge.indexOf('refs/heads/') !== 0) {
      return shortBranch
    }

    return branchMerge.substring(11)
  }

  // Internal
  remoteBranchName () {
    const gitConfigBranch = this.repo.getConfigValue('atom.open-on-github.branch', this.filePath)

    if (gitConfigBranch) {
      return gitConfigBranch
    } else if (this.remoteName() != null) {
      return this.encodeSegments(this.branchName())
    } else {
      return 'master'
    }
  }
}
<commit_msg>Support wiki history<commit_after>/** @babel */

import {shell} from 'electron'
import {Range} from 'atom'
import {parse as parseURL} from 'url'
import path from 'path'

export default class GitHubFile {
  // Public
  static fromPath (filePath) {
    return new GitHubFile(filePath)
  }

  constructor (filePath) {
    this.filePath = filePath
    const [rootDir] = atom.project.relativizePath(this.filePath)

    if (rootDir != null) {
      const rootDirIndex = atom.project.getPaths().indexOf(rootDir)
      this.repo = atom.project.getRepositories()[rootDirIndex]
    }
  }

  // Public
  open (lineRange) {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.blobURL() + this.getLineRangeSuffix(lineRange))
    }
  }

  // Public
  openOnMaster (lineRange) {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.blobURLForMaster() + this.getLineRangeSuffix(lineRange))
    }
  }

  // Public
  blame (lineRange) {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.blameURL() + this.getLineRangeSuffix(lineRange))
    }
  }

  history () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.historyURL())
    }
  }

  copyURL (lineRange) {
    if (this.validateRepo()) {
      atom.clipboard.write(this.shaURL() + this.getLineRangeSuffix(lineRange))
    }
  }

  openBranchCompare () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.branchCompareURL())
    }
  }

  openIssues () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.issuesURL())
    }
  }

  openPullRequests () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.pullRequestsURL())
    }
  }

  openRepository () {
    if (this.validateRepo()) {
      this.openURLInBrowser(this.githubRepoURL())
    }
  }

  getLineRangeSuffix (lineRange) {
    if (lineRange && !this.isGitHubWikiURL(this.githubRepoURL()) && atom.config.get('open-on-github.includeLineNumbersInUrls')) {
      lineRange = Range.fromObject(lineRange)
      const startRow = lineRange.start.row + 1
      const endRow = lineRange.end.row + 1

      if (startRow === endRow) {
        if (this.isGistURL(this.githubRepoURL())) {
          return `-L${startRow}`
        } else {
          return `#L${startRow}`
        }
      } else {
        if (this.isGistURL(this.githubRepoURL())) {
          return `-L${startRow}-L${endRow}`
        } else {
          return `#L${startRow}-L${endRow}`
        }
      }
    } else {
      return ''
    }
  }

  // Internal
  validateRepo () {
    if (!this.repo) {
      atom.notifications.addWarning(`No repository found for path: ${this.filePath}.`)
      return false
    } else if (!this.gitURL()) {
      atom.notifications.addWarning(`No URL defined for remote: ${this.remoteName()}`)
      return false
    } else if (!this.githubRepoURL()) {
      atom.notifications.addWarning(`Remote URL is not hosted on GitHub: ${this.gitURL()}`)
      return false
    }
    return true
  }

  // Internal
  openURLInBrowser (url) {
    shell.openExternal(url)
  }

  // Internal
  blobURL () {
    const gitHubRepoURL = this.githubRepoURL()
    const repoRelativePath = this.repoRelativePath()

    if (this.isGitHubWikiURL(gitHubRepoURL)) {
      return `${gitHubRepoURL.slice(0, -5)}/wiki/${this.extractFileName(repoRelativePath)}`
    } else if (this.isGistURL(gitHubRepoURL)) {
      return `${gitHubRepoURL}#file-${this.encodeSegments(repoRelativePath.replace(/\./g, '-'))}`
    } else {
      return `${gitHubRepoURL}/blob/${this.remoteBranchName()}/${this.encodeSegments(repoRelativePath)}`
    }
  }

  // Internal
  blobURLForMaster () {
    const gitHubRepoURL = this.githubRepoURL()

    if (this.isGitHubWikiURL(gitHubRepoURL) || this.isGistURL(gitHubRepoURL)) {
      return this.blobURL() // Gists do not have branches
    } else {
      return `${gitHubRepoURL}/blob/master/${this.encodeSegments(this.repoRelativePath())}`
    }
  }

  // Internal
  shaURL () {
    const gitHubRepoURL = this.githubRepoURL()
    const encodedSHA = this.encodeSegments(this.sha())
    const repoRelativePath = this.repoRelativePath()

    if (this.isGitHubWikiURL(gitHubRepoURL)) {
      return `${gitHubRepoURL.slice(0, -5)}/wiki/${this.extractFileName(repoRelativePath)}/${encodedSHA}`
    } else if (this.isGistURL(gitHubRepoURL)) {
      return `${gitHubRepoURL}/${encodedSHA}#file-${this.encodeSegments(repoRelativePath.replace(/\./g, '-'))}`
    } else {
      return `${gitHubRepoURL}/blob/${encodedSHA}/${this.encodeSegments(repoRelativePath)}`
    }
  }

  // Internal
  blameURL () {
    return `${this.githubRepoURL()}/blame/${this.remoteBranchName()}/${this.encodeSegments(this.repoRelativePath())}`
  }

  // Internal
  historyURL () {
    const gitHubRepoURL = this.githubRepoURL()

    if (this.isGitHubWikiURL(gitHubRepoURL)) {
      return `${gitHubRepoURL.slice(0, -5)}/wiki/${this.extractFileName(this.repoRelativePath())}/_history`
    } else if (this.isGistURL(gitHubRepoURL)) {
      return `${gitHubRepoURL}/revisions`
    } else {
      return `${gitHubRepoURL}/commits/${this.remoteBranchName()}/${this.encodeSegments(this.repoRelativePath())}`
    }
  }

  // Internal
  issuesURL () {
    return `${this.githubRepoURL()}/issues`
  }

  // Internal
  pullRequestsURL () {
    return `${this.githubRepoURL()}/pulls`
  }

  // Internal
  branchCompareURL () {
    return `${this.githubRepoURL()}/compare/${this.encodeSegments(this.branchName())}`
  }

  encodeSegments (segments = '') {
    return segments.split('/').map(segment => encodeURIComponent(segment)).join('/')
  }

  // Internal
  extractFileName (relativePath = '') {
    return path.parse(relativePath).name
  }

  // Internal
  gitURL () {
    const remoteName = this.remoteName()
    if (remoteName != null) {
      return this.repo.getConfigValue(`remote.${remoteName}.url`, this.filePath)
    } else {
      return this.repo.getConfigValue(`remote.origin.url`, this.filePath)
    }
  }

  // Internal
  githubRepoURL () {
    let url = this.gitURL()

    if (url.match(/git@[^:]+:/)) {
      url = url.replace(/^git@([^:]+):(.+)$/, (match, host, repoPath) => {
        repoPath = repoPath.replace(/^\/+/, '')
        return `http://${host}/${repoPath}`
      })
    } else if (url.match(/ssh:\/\/git@([^/]+)\//)) {
      url = `http://${url.substring(10)}`
    } else if (url.match(/^git:\/\/[^/]+\//)) {
      url = `http${url.substring(3)}`
    }

    // Remove trailing .git and trailing slashes
    url = url.replace(/\.git$/, '').replace(/\/+$/, '')

    if (!this.isBitbucketURL(url)) {
      return url
    }
  }

  isGistURL (url) {
    try {
      const {host} = parseURL(url)

      return host === 'gist.github.com'
    } finally {}
  }

  isGitHubWikiURL (url) {
    return /\.wiki$/.test(url)
  }

  isBitbucketURL (url) {
    if (url.startsWith('git@bitbucket.org')) {
      return true
    }

    try {
      const {host} = parseURL(url)

      return host === 'bitbucket.org'
    } finally {}
  }

  // Internal
  repoRelativePath () {
    return this.repo.getRepo(this.filePath).relativize(this.filePath)
  }

  // Internal
  remoteName () {
    const gitConfigRemote = this.repo.getConfigValue('atom.open-on-github.remote', this.filePath)

    if (gitConfigRemote) {
      return gitConfigRemote
    }

    const shortBranch = this.repo.getShortHead(this.filePath)

    if (!shortBranch) {
      return null
    }

    const branchRemote = this.repo.getConfigValue(`branch.${shortBranch}.remote`, this.filePath)

    if (branchRemote && branchRemote.length > 0) {
      return branchRemote
    }

    return null
  }

  // Internal
  sha () {
    return this.repo.getReferenceTarget('HEAD', this.filePath)
  }

  // Internal
  branchName () {
    const shortBranch = this.repo.getShortHead(this.filePath)

    if (!shortBranch) {
      return null
    }

    const branchMerge = this.repo.getConfigValue(`branch.${shortBranch}.merge`, this.filePath)
    if (!(branchMerge && branchMerge.length > 11)) {
      return shortBranch
    }

    if (branchMerge.indexOf('refs/heads/') !== 0) {
      return shortBranch
    }

    return branchMerge.substring(11)
  }

  // Internal
  remoteBranchName () {
    const gitConfigBranch = this.repo.getConfigValue('atom.open-on-github.branch', this.filePath)

    if (gitConfigBranch) {
      return gitConfigBranch
    } else if (this.remoteName() != null) {
      return this.encodeSegments(this.branchName())
    } else {
      return 'master'
    }
  }
}
<|endoftext|>


<commit_before>#! /usr/bin/env node

/*
 * gog-scraper
 * Copyright (c) 2016 Jeff Minnear
 * Licensed under the MIT license.
 */

'use strict';

var program = require('commander');
var request = require('request');
var cheerio = require('cheerio');
const chalk = require('chalk');
var colorLegend = "Prices in " + chalk.green("green") + " are current sale prices, shown next to their normal price in " + chalk.gray("gray") + ".";
var gogSearchUrl =
<commit_msg>Get JSON response from site<commit_after>#! /usr/bin/env node

/*
 * gog-scraper
 * Copyright (c) 2016 Jeff Minnear
 * Licensed under the MIT license.
 */

'use strict';

var program = require('commander');
var request = require('request');
var cheerio = require('cheerio');
const chalk = require('chalk');
var colorLegend = "Prices in " + chalk.green("green") + " are current sale prices, shown next to their normal price in " + chalk.gray("gray") + ".";

program
    .version('0.0.1')
    .option('-t, --title <string>', 'the title of the game you want to price-check', String)
    .option('-l, --limit <n>', 'the number of results you want to see (default is 1)', Number)
    .parse(process.argv);

var gogSearchUrl = 'http://www.gog.com/games/ajax/filtered?limit=' + program.limit + '&search=';
var gameSearchUrl = gogSearchUrl + encodeURIComponent(program.title);
console.log(colorLegend);

request(gameSearchUrl, function(error, response, body){
    if (!error) {
        var json = JSON.parse(body);

        console.log(json.products);
    }
});
<|endoftext|>