<commit_before>(function(window) {
    function isPromise(o) {
        return o instanceof Promise
    }

    function flattenPromise (obj) {
        if (obj instanceof Promise) {
            return Promise.resolve(obj);
        }

        if (obj instanceof Array) {
            return new Promise(function (resolve) {
                var promises = obj.map(function (o) {
                    return flattenPromise(o);
                });

                return Promise.all(promises).then(function (res) {
                    for (var i = 0; i < obj.length; i++) {
                        obj[i] = res[i];
                    }
                    resolve(obj);
                });
            });
        }

        if (obj instanceof Object) {
            return new Promise(function (resolve) {
                var keys = Object.keys(obj);
                var promises = keys.map(function (key) {
                    return flattenPromise(obj[key]);
                });

                return Promise.all(promises).then(function (res) {
                    for (var i = 0; i < keys.length; i++) {
                        obj[keys[i]] = res[i];
                    }
                    resolve(obj);
                });
            });
        }

        return Promise.resolve(obj);
    };

    var ethMethods = function () {
        var blockCall = function (args) {
            return typeof args[0] === "string" ? "blockByHash" : "blockByNumber";
        };

        var transactionCall = function (args) {
            return typeof args[0] === "string" ? 'transactionByHash' : 'transactonByNumber';
        };

        var uncleCall = function (args) {
            return typeof args[0] === "string" ? 'uncleByHash' : 'uncleByNumber';
        };

        var methods = [
        { name: 'balanceAt', call: 'balanceAt' },
        { name: 'stateAt', call: 'stateAt' },
        { name: 'countAt', call: 'countAt'},
        { name: 'codeAt', call: 'codeAt' },
        { name: 'transact', call: 'transact' },
        { name: 'call', call: 'call' },
        { name: 'block', call: blockCall },
        { name: 'transaction', call: transactionCall },
        { name: 'uncle', call: uncleCall },
        { name: 'compile', call: 'compile' }
        ];
        return methods;
    };

    var ethProperties = function () {
        return [
        { name: 'coinbase', getter: 'coinbase', setter: 'setCoinbase' },
        { name: 'listening', getter: 'listening', setter: 'setListening' },
        { name: 'mining', getter: 'mining', setter: 'setMining' },
        { name: 'gasPrice', getter: 'gasPrice' },
        { name: 'accounts', getter: 'accounts' },
        { name: 'peerCount', getter: 'peerCount' },
        { name: 'defaultBlock', getter: 'defaultBlock', setter: 'setDefaultBlock' },
        { name: 'number', getter: 'number'}
        ];
    };

    var dbMethods = function () {
        return [
        { name: 'put', call: 'put' },
        { name: 'get', call: 'get' },
        { name: 'putString', call: 'putString' },
        { name: 'getString', call: 'getString' }
        ];
    };

    var shhMethods = function () {
        return [
        { name: 'post', call: 'post' },
        { name: 'newIdentity', call: 'newIdentity' },
        { name: 'haveIdentity', call: 'haveIdentity' },
        { name: 'newGroup', call: 'newGroup' },
        { name: 'addToGroup', call: 'addToGroup' }
        ];
    };

    var setupMethods = function (obj, methods) {
        methods.forEach(function (method) {
            obj[method.name] = function () {
                return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) {
                    var call = typeof method.call === "function" ? method.call(args) : method.call;
                    return {call: call, args: args};
                }).then(function (request) {
                    return new Promise(function (resolve, reject) {
                        web3.provider.send(request, function (result) {
                            if (result) {
                                resolve(result);
                            } else {
                                reject(result);
                            }
                        });
                    });
                }).catch(function( err) {
                    console.error(err);
                });
            };
        });
    };

    var setupProperties = function (obj, properties) {
        properties.forEach(function (property) {
            var proto = {};
            proto.get = function () {
                return new Promise(function(resolve, reject) {
                    web3.provider.send({call: property.getter}, function(result) {
                        resolve(result);
                    });
                });
            };
            if (property.setter) {
                proto.set = function (val) {
                    return flattenPromise([val]).then(function (args) {
                        return new Promise(function (resolve) {
                            web3.provider.send({call: property.setter, args: args}, function (result) {
                                if (result) {
                                    resolve(result);
                                } else {
                                    reject(result);
                                }
                            });
                        });
                    }).catch(function (err) {
                        console.error(err);
                    });
                }
            }
            Object.defineProperty(obj, property.name, proto);
        });
    };

    var web3 = {
        _callbacks: {},
        _events: {},
        providers: {},
        toHex: function(str) {
            var hex = "";
            for(var i = 0; i < str.length; i++) {
                var n = str.charCodeAt(i).toString(16);
                hex += n.length < 2 ? '0' + n : n;
            }

            return hex;
        },

        toAscii: function(hex) {
            // Find termination
            var str = "";
            var i = 0, l = hex.length;
            for(; i < l; i+=2) {
                var code = hex.charCodeAt(i)
                if(code == 0) {
                    break;
                }

                str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
            }

            return str;
        },

        fromAscii: function(str, pad) {
            if(pad === undefined) {
                pad = 32
            }

            var hex = this.toHex(str);

            while(hex.length < pad*2)
                hex += "00";

            return hex
        },

        eth: {
            prototype: Object(),
            watch: function(params) {
                return new Filter(params);
            },
        },

        db: {
            prototype: Object()
        },

        shh: {
            prototype: Object()
        },

        on: function(event, cb) {
            if(web3._events[event] === undefined) {
                web3._events[event] = [];
            }

            web3._events[event].push(cb);

            return this
        },

        off: function(event, cb) {
            if(web3._events[event] !== undefined) {
                var callbacks = web3._events[event];
                for(var i = 0; i < callbacks.length; i++) {
                    if(callbacks[i] === cb) {
                        delete callbacks[i];
                    }
                }
            }

            return this
        },

        trigger: function(event, data) {
            var callbacks = web3._events[event];
            if(callbacks !== undefined) {
                for(var i = 0; i < callbacks.length; i++) {
                    // Figure out whether the returned data was an array
                    // array means multiple return arguments (multiple params)
                    if(data instanceof Array) {
                        callbacks[i].apply(this, data);
                    } else {
                        callbacks[i].call(this, undefined, data);
                    }
                }
            }
        },
    };

    var eth = web3.eth;
    setupMethods(eth, ethMethods());
    setupProperties(eth, ethProperties());
    setupMethods(web3.db, dbMethods());
    setupMethods(web3.shh, shhMethods());

    var ProviderManager = function() {
        this.queued = [];
        this.polls = [];
        this.ready = false;
        this.provider = undefined;
        this.id = 1;

        var self = this;
        var poll = function () {
            if (self.provider && self.provider.poll) {
                self.polls.forEach(function (data) {
                    data.data._id = self.id;
                    self.id++;
                    self.provider.poll(data.data, data.id);
                });
            }
            setTimeout(poll, 12000);
        };
        poll();
    };

    ProviderManager.prototype.send = function(data, cb) {
        data._id = this.id;
        if(cb) {
            web3._callbacks[data._id] = cb;
        }

        if(data.args === undefined) {
            data.args = [];
        }

        this.id++;

        if(this.provider !== undefined) {
            this.provider.send(data);
        } else {
            console.warn("provider is not set");
            this.queued.push(data);
        }
    };

    ProviderManager.prototype.set = function(provider) {
        if(this.provider !== undefined && this.provider.unload !== undefined) {
            this.provider.unload();
        }

        this.provider = provider;
        this.ready = true;
    };

    ProviderManager.prototype.sendQueued = function() {
        for(var i = 0; this.queued.length; i++) {
            // Resend
            this.send(this.queued[i]);
        }
    };

    ProviderManager.prototype.installed = function() {
        return this.provider !== undefined;
    };

    ProviderManager.prototype.startPolling = function (data, pollId) {
        if (!this.provider || !this.provider.poll) {
            return;
        }
        this.polls.push({data: data, id: pollId});
    };

    ProviderManager.prototype.stopPolling = function (pollId) {
        for (var i = this.polls.length; i--;) {
            var poll = this.polls[i];
            if (poll.id === pollId) {
                this.polls.splice(i, 1);
            }
        }
    };

    web3.provider = new ProviderManager();

    web3.setProvider = function(provider) {
        provider.onmessage = messageHandler;

        web3.provider.set(provider);

        web3.provider.sendQueued();
    };

    var filters = [];
    var Filter = function(options) {
        filters.push(this);

        this.callbacks = [];
        this.options = options;

        var call;
        if(options === "chain" || options === "pending") {
            call = "newFilterString"
        } else if(typeof options === "object") {
            call = "newFilter"
        }

        var self = this; // Cheaper than binding
        this.promise = new Promise(function(resolve, reject) {
            web3.provider.send({call: call, args: [options]}, function(id) {
                self.id = id;
                web3.provider.startPolling({call: "changed", args: [id]}, id);
                resolve(id);
            });
        });
    };

    Filter.prototype.changed = function(callback) {
        var self = this;
        this.promise.then(function(id) {
            self.callbacks.push(callback);
        });
    };

    Filter.prototype.trigger = function(messages, id) {
        if(id == this.id) {
            for(var i = 0; i < this.callbacks.length; i++) {
                this.callbacks[i].call(this, messages);
            }
        }
    };

    Filter.prototype.uninstall = function() {
        this.promise.then(function(id) {
            web3.provider.send({call: "uninstallFilter", args:[id]});
            web3.provider.stopPolling(id);
        });
    };

    Filter.prototype.messages = function() {
        var self=this;
        return Promise.all([this.promise]).then(function() {
            var id = self.id
            return new Promise(function(resolve, reject) {
                web3.provider.send({call: "getMessages", args: [id]}, function(messages) {
                    resolve(messages);
                });
            });
        });
    };

    // Register to the messages callback. "messages" will be emitted when new messages
    // from the client have been created.
    web3.on("messages", function(messages, id) {
        for(var i = 0; i < filters.length; i++) {
            filters[i].trigger(messages, id);
        }
    });

    function messageHandler(data) {
        if(data._event !== undefined) {
            web3.trigger(data._event, data.data);
        } else {
            if(data._id) {
                var cb = web3._callbacks[data._id];
                if(cb) {
                    cb.call(this, data.data)

                    // Remove the "trigger" callback
                    delete web3._callbacks[data._id];
                }
            }
        }
    }

    /*
    // Install default provider
    if(!web3.provider.installed()) {
        var sock = new web3.WebSocket("ws://localhost:40404/eth");

        web3.setProvider(sock);
    }
    */

    window.web3 = web3;

})(this);
<commit_msg>polling whisper in progress<commit_after>(function(window) {
    function isPromise(o) {
        return o instanceof Promise
    }

    function flattenPromise (obj) {
        if (obj instanceof Promise) {
            return Promise.resolve(obj);
        }

        if (obj instanceof Array) {
            return new Promise(function (resolve) {
                var promises = obj.map(function (o) {
                    return flattenPromise(o);
                });

                return Promise.all(promises).then(function (res) {
                    for (var i = 0; i < obj.length; i++) {
                        obj[i] = res[i];
                    }
                    resolve(obj);
                });
            });
        }

        if (obj instanceof Object) {
            return new Promise(function (resolve) {
                var keys = Object.keys(obj);
                var promises = keys.map(function (key) {
                    return flattenPromise(obj[key]);
                });

                return Promise.all(promises).then(function (res) {
                    for (var i = 0; i < keys.length; i++) {
                        obj[keys[i]] = res[i];
                    }
                    resolve(obj);
                });
            });
        }

        return Promise.resolve(obj);
    };

    var ethMethods = function () {
        var blockCall = function (args) {
            return typeof args[0] === "string" ? "blockByHash" : "blockByNumber";
        };

        var transactionCall = function (args) {
            return typeof args[0] === "string" ? 'transactionByHash' : 'transactonByNumber';
        };

        var uncleCall = function (args) {
            return typeof args[0] === "string" ? 'uncleByHash' : 'uncleByNumber';
        };

        var methods = [
        { name: 'balanceAt', call: 'balanceAt' },
        { name: 'stateAt', call: 'stateAt' },
        { name: 'countAt', call: 'countAt'},
        { name: 'codeAt', call: 'codeAt' },
        { name: 'transact', call: 'transact' },
        { name: 'call', call: 'call' },
        { name: 'block', call: blockCall },
        { name: 'transaction', call: transactionCall },
        { name: 'uncle', call: uncleCall },
        { name: 'compile', call: 'compile' }
        ];
        return methods;
    };

    var ethProperties = function () {
        return [
        { name: 'coinbase', getter: 'coinbase', setter: 'setCoinbase' },
        { name: 'listening', getter: 'listening', setter: 'setListening' },
        { name: 'mining', getter: 'mining', setter: 'setMining' },
        { name: 'gasPrice', getter: 'gasPrice' },
        { name: 'accounts', getter: 'accounts' },
        { name: 'peerCount', getter: 'peerCount' },
        { name: 'defaultBlock', getter: 'defaultBlock', setter: 'setDefaultBlock' },
        { name: 'number', getter: 'number'}
        ];
    };

    var dbMethods = function () {
        return [
        { name: 'put', call: 'put' },
        { name: 'get', call: 'get' },
        { name: 'putString', call: 'putString' },
        { name: 'getString', call: 'getString' }
        ];
    };

    var shhMethods = function () {
        return [
        { name: 'post', call: 'post' },
        { name: 'newIdentity', call: 'newIdentity' },
        { name: 'haveIdentity', call: 'haveIdentity' },
        { name: 'newGroup', call: 'newGroup' },
        { name: 'addToGroup', call: 'addToGroup' }
        ];
    };

    var ethWatchMethods = function () {
        var newFilter = function (args) {
            return typeof args[0] === 'string' ? 'newFilterString' : 'newFilter';
        };

        return [
        { name: 'newFilter', call: newFilter },
        { name: 'uninstallFilter', call: 'uninstallFilter' },
        { name: 'changed', call: 'changed' },
        { name: 'getMessages', call: 'getMessages' }
        ];
    };

    var shhWatchMethods = function () {
        return [
        { name: 'newFilter', call: 'shhNewFilter' },
        { name: 'uninstallFilter', call: 'shhUninstallFilter' },
        { name: 'changed', call: 'shhChanged' },
        { name: 'getMessage', call: 'shhGetMessages' }
        ];
    };

    var setupMethods = function (obj, methods) {
        methods.forEach(function (method) {
            obj[method.name] = function () {
                return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) {
                    var call = typeof method.call === "function" ? method.call(args) : method.call;
                    return {call: call, args: args};
                }).then(function (request) {
                    return new Promise(function (resolve, reject) {
                        web3.provider.send(request, function (result) {
                            if (result) {
                                resolve(result);
                            } else {
                                reject(result);
                            }
                        });
                    });
                }).catch(function( err) {
                    console.error(err);
                });
            };
        });
    };

    var setupProperties = function (obj, properties) {
        properties.forEach(function (property) {
            var proto = {};
            proto.get = function () {
                return new Promise(function(resolve, reject) {
                    web3.provider.send({call: property.getter}, function(result) {
                        resolve(result);
                    });
                });
            };
            if (property.setter) {
                proto.set = function (val) {
                    return flattenPromise([val]).then(function (args) {
                        return new Promise(function (resolve) {
                            web3.provider.send({call: property.setter, args: args}, function (result) {
                                if (result) {
                                    resolve(result);
                                } else {
                                    reject(result);
                                }
                            });
                        });
                    }).catch(function (err) {
                        console.error(err);
                    });
                }
            }
            Object.defineProperty(obj, property.name, proto);
        });
    };

    var web3 = {
        _callbacks: {},
        _events: {},
        providers: {},
        toHex: function(str) {
            var hex = "";
            for(var i = 0; i < str.length; i++) {
                var n = str.charCodeAt(i).toString(16);
                hex += n.length < 2 ? '0' + n : n;
            }

            return hex;
        },

        toAscii: function(hex) {
            // Find termination
            var str = "";
            var i = 0, l = hex.length;
            for(; i < l; i+=2) {
                var code = hex.charCodeAt(i)
                if(code == 0) {
                    break;
                }

                str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
            }

            return str;
        },

        toDecimal: function (val) {
            return parseInt(val, 16);
        },

        fromAscii: function(str, pad) {
            if(pad === undefined) {
                pad = 32
            }

            var hex = this.toHex(str);

            while(hex.length < pad*2)
                hex += "00";

            return hex
        },

        eth: {
            prototype: Object(),
            watch: function (params) {
                return new Filter(params, ethWatch);
            },
        },

        db: {
            prototype: Object()
        },

        shh: {
            prototype: Object(),
            watch: function (params) {
                return new Filter(params, shhWatch);
            }
        },

        on: function(event, cb) {
            if(web3._events[event] === undefined) {
                web3._events[event] = [];
            }

            web3._events[event].push(cb);

            return this
        },

        off: function(event, cb) {
            if(web3._events[event] !== undefined) {
                var callbacks = web3._events[event];
                for(var i = 0; i < callbacks.length; i++) {
                    if(callbacks[i] === cb) {
                        delete callbacks[i];
                    }
                }
            }

            return this
        },

        trigger: function(event, data) {
            var callbacks = web3._events[event];
            if(callbacks !== undefined) {
                for(var i = 0; i < callbacks.length; i++) {
                    // Figure out whether the returned data was an array
                    // array means multiple return arguments (multiple params)
                    if(data instanceof Array) {
                        callbacks[i].apply(this, data);
                    } else {
                        callbacks[i].call(this, undefined, data);
                    }
                }
            }
        },
    };

    var eth = web3.eth;
    setupMethods(eth, ethMethods());
    setupProperties(eth, ethProperties());
    setupMethods(web3.db, dbMethods());
    setupMethods(web3.shh, shhMethods());

    var ethWatch = {};
    setupMethods(ethWatch, ethWatchMethods());
    var shhWatch = {};
    setupMethods(shhWatch, shhWatchMethods());

    var ProviderManager = function() {
        this.queued = [];
        this.polls = [];
        this.ready = false;
        this.provider = undefined;
        this.id = 1;

        var self = this;
        var poll = function () {
            if (self.provider && self.provider.poll) {
                self.polls.forEach(function (data) {
                    data.data._id = self.id;
                    self.id++;
                    self.provider.poll(data.data, data.id);
                });
            }
            setTimeout(poll, 12000);
        };
        poll();
    };

    ProviderManager.prototype.send = function(data, cb) {
        data._id = this.id;
        if(cb) {
            web3._callbacks[data._id] = cb;
        }

        if(data.args === undefined) {
            data.args = [];
        }

        this.id++;

        if(this.provider !== undefined) {
            this.provider.send(data);
        } else {
            console.warn("provider is not set");
            this.queued.push(data);
        }
    };

    ProviderManager.prototype.set = function(provider) {
        if(this.provider !== undefined && this.provider.unload !== undefined) {
            this.provider.unload();
        }

        this.provider = provider;
        this.ready = true;
    };

    ProviderManager.prototype.sendQueued = function() {
        for(var i = 0; this.queued.length; i++) {
            // Resend
            this.send(this.queued[i]);
        }
    };

    ProviderManager.prototype.installed = function() {
        return this.provider !== undefined;
    };

    ProviderManager.prototype.startPolling = function (data, pollId) {
        if (!this.provider || !this.provider.poll) {
            return;
        }
        this.polls.push({data: data, id: pollId});
    };

    ProviderManager.prototype.stopPolling = function (pollId) {
        for (var i = this.polls.length; i--;) {
            var poll = this.polls[i];
            if (poll.id === pollId) {
                this.polls.splice(i, 1);
            }
        }
    };

    web3.provider = new ProviderManager();

    web3.setProvider = function(provider) {
        provider.onmessage = messageHandler;
        web3.provider.set(provider);
        web3.provider.sendQueued();
    };

    var filters = [];
    var Filter = function(options, impl) {
        filters.push(this);

        this.impl = impl;
        this.callbacks = [];

        var self = this; // Cheaper than binding
        this.promise = impl.newFilter(options);
        this.promise.then(function (id) {
            self.id = id;
            web3.provider.startPolling({call: 'changed', args: [id]}, id);
        });
    };

    Filter.prototype.changed = function(callback) {
        var self = this;
        this.promise.then(function(id) {
            self.callbacks.push(callback);
        });
    };

    Filter.prototype.trigger = function(messages, id) {
        if(id == this.id) {
            for(var i = 0; i < this.callbacks.length; i++) {
                this.callbacks[i].call(this, messages);
            }
        }
    };

    Filter.prototype.uninstall = function() {
        var self = this;
        this.promise.then(function (id) {
            self.impl.uninstallFilter(id);
            web3.provider.stopPolling(id);
        });
    };

    Filter.prototype.messages = function() {
        var self = this;
        return this.promise.then(function (id) {
            return self.impl.getMessages(id);
        });
    };

    // Register to the messages callback. "messages" will be emitted when new messages
    // from the client have been created.
    web3.on("messages", function(messages, id) {
        for(var i = 0; i < filters.length; i++) {
            filters[i].trigger(messages, id);
        }
    });

    function messageHandler(data) {
        if(data._event !== undefined) {
            web3.trigger(data._event, data.data);
        } else {
            if(data._id) {
                var cb = web3._callbacks[data._id];
                if(cb) {
                    cb.call(this, data.data)

                    // Remove the "trigger" callback
                    delete web3._callbacks[data._id];
                }
            }
        }
    }

    /*
    // Install default provider
    if(!web3.provider.installed()) {
        var sock = new web3.WebSocket("ws://localhost:40404/eth");

        web3.setProvider(sock);
    }
    */

    window.web3 = web3;

})(this);
<|endoftext|>


<commit_before>//Requires for the other roles and modules

//Roles
var roleHarvester = require('role.harvester');
var roleMiner = require('role.miner');
var roleHauler = require('role.hauler');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleRepair = require('role.repair');
var roleArchitect = require('role.architect');
var roleFeeder = require('role.feeder');

//Modules
var modSpawning = require('module.spawning');
var modCommon = require('module.common');
var modStructures = require('module.structures');

//Initial memory JSON for the roles
//includes counters for roles and maxes
var initialRolesMem = {
    "numCreeps":0,
    "numHarvesters":0,
    "maxHarvesters":1,
    "numUpgraders":0,
    "maxUpgraders":0,
    "numBuilders":0,
    "maxBuilders":1,
    "numRepair":0,
    "maxRepair":1,
    "numArchitects":0,
    "betterHarvesters1":0,
    "betterHarvesters2":0,
    "numMiners":0,
    "maxMiners":0,
    "numHaulers":0,
    "maxHaulers":1,
    "numFeeders":0,
    "maxFeeders":1

};

//Tower initial memory JSON
var initialTowerMem = {
  "target":null,
  "mode":"attack",
  "fixe":null
};

//Set all the above JSONs into memeory on first start
function initialize(){
  //TODO make these per room
  Memory.roles = initialRolesMem;
  Memory.towersMem = initialTowerMem;
  Memory.initialized = true;
  Memory.conservation = false;
  Memory.fortify = false;
}

//Gets the number of living harvester Creeps
function getNumHarvesters(creepList){
  var harvesters = _.filter(creepList, (creep) => creep.memory.role == 'harvester');
  var hL = harvesters.length;
  if(Memory.roles.numHarvesters != hL){
    Memory.roles.numHarvesters = hL;
    console.log('Harvesters: ' + hL);
  }
  return hL;
}

//Gets the number of living upgrader Creeps
function getNumUpgraders(creepList){
  var upgraders = _.filter(creepList, (creep) => creep.memory.role == 'upgrader');
  var uL = upgraders.length;
  if(Memory.roles.numUpgraders != uL){
    Memory.roles.numUpgraders = uL;
    console.log('Upgraders: ' + uL);
  }
  return uL;
}

//Gets the number of living builder Creeps
function getNumBuilders(creepList){
  var builders = _.filter(creepList, (creep) => creep.memory.role == 'builder');
  var bL = builders.length;
  if(Memory.roles.numBuilders != bL){
    Memory.roles.numBuilders = bL;
    console.log('Builders: ' + bL);
  }
  return bL;
}

//Gets the number of living Repair Creeps
function getNumRepair(creepList){
  var repair = _.filter(creepList, (creep) => creep.memory.role == 'repair');
  var rL = repair.length;
  if(Memory.roles.numRepair != rL){
    Memory.roles.numRepair = rL;
    console.log('Repair: ' + rL);
  }
  return rL;
}

//Gets the number of living architect Creeps
function getNumArchitects(creepList){
  var architects = _.filter(creepList, (creep) => creep.memory.role == 'architect');
  var aL = architects.length;
  if(Memory.roles.numArchitects != aL){
    Memory.roles.numArchitects = aL;
    console.log('Architects: ' + aL);
  }
  return aL;
}

//Gets the number of living miner Creeps
function getNumMiners(creepList){
  var miners = _.filter(creepList, (creep) => creep.memory.role == 'miner');
  var mL = miners.length;
  if(Memory.roles.numMiners != mL){
    Memory.roles.numMiners = mL;
    console.log('Miners: ' + mL);
  }
  return mL;
}

//Gets the number of living hauler Creeps
function getNumHaulers(creepList){
  var haulers = _.filter(creepList, (creep) => creep.memory.role == 'hauler');
  var haulL = haulers.length;
  if(Memory.roles.numHaulers != haulL){
    Memory.roles.numHaulers = haulL;
    console.log('Haulers: ' + haulL);
  }
  return haulL;
}

function getNumFeeders(creepList){
  var feeders = _.filter(creepList, (creep) => creep.memory.role == 'feeder');
  var feedL = feeders.length;
  if(Memory.roles.numFeeders != feedL){
    Memory.roles.numFeeders = feedL;
    console.log('Haulers: ' + feedL);
  }
  return haulL;
}

//main loop
module.exports.loop = function () {

  //Only initialize if it hasnt been done (or it was manually set to false)
  if(Memory.initialized!==true){
    initialize();
  }

  //Loop to check each room that is visible to the script
  for(var roomName in Game.rooms){
    var room = Game.rooms[roomName];

    if(Memory.fortify && (!room.controller.safeMode || room.controller.safeMode<1000)){
      Memory.fortify = false;
    }

    //Creep lists in each room, comparing lengths shows if there are 'others'
    var allCreepList = room.find(FIND_CREEPS);
    var myCreepList = _.filter(allCreepList, (creep) => (creep.owner && creep.owner.username ==="PCarton"));
    var enemyPresent = allCreepList.length>myCreepList.length;

    //Al the structures in the room that are controlled by the player
    var allStructs = room.find(FIND_MY_STRUCTURES);
    var towers = _.filter(allStructs, (struct) => struct.structureType === STRUCTURE_TOWER);

    //calculates the breakdown of creeps by roles
    var h  = getNumHarvesters(myCreepList);
    var u = getNumUpgraders(myCreepList);
    var b = getNumBuilders(myCreepList);
    var r = getNumRepair(myCreepList);
    var a = getNumArchitects(myCreepList);
    var m = getNumMiners(myCreepList);
    var ha = getNumHaulers(myCreepList);
    var f = getNumFeeders(myCreepList);
    Memory.roles.numCreeps = h + u + b + r + a + m + ha + f;

    //Clear dead creeps from memory
    modCommon.clearDead();

    //assign the right run method to each creep based on its role
    for(var name in myCreepList) {
        var creep = myCreepList[name];

        //Has the non-military creeps retreat
        //Mining creeps are considered military - like the supply line
        if(enemyPresent && creep.memory.military !== true){
          modCommon.retreat(creep);
        }
        //If there are no enemies, run the appropriate role method
        else if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        else if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        else if(creep.memory.role == 'builder'){
          roleBuilder.run(creep);
        }
        else if(creep.memory.role == 'repair'){
          roleRepair.run(creep);
        }
        else if(creep.memory.role == 'architect'){
          roleArchitect.run(creep);
        }
        else if(creep.memory.role == 'miner'){
          roleMiner.run(creep);
        }
        else if(creep.memory.role == 'hauler'){
          roleHauler.run(creep);
        }
        else if(creep.memory.role == 'feeder'){
          roleFeeder.run(creep);
        }
    }

    //determine if new creeps need to be spawned and pick an appropriate spawner
    //Spawn logic is in a seperate module
    if(Memory.roles.numCreeps < modSpawning.maxCreeps){
        for(var spawn in Game.spawns){
          var spawner = Game.spawns[spawn];
          var controllerLvl= spawner.room.controller.level;
          var energyCapacity = spawner.room.energyCapacityAvailable;
          modSpawning.spawn(spawner,energyCapacity,controllerLvl);

        }
    }

    var control = room.controller;

    if(enemyPresent && modCommon.playerAttack(allCreepList) && !(control.safeMode || control.safeModeCooldown) && control.safeModeAvailable > 0 ){
      control.activateSafeMode();
      Memory.fortify = true;
      Game.notify("Activated Safe Mode");
    }

    //Variable to keep track of which enemy to shoot
    var target = Game.getObjectById(Memory.towersMem.target);

    //Notify the user on enemies or switch to healing and repairing
    if(enemyPresent){
      Memory.towersMem.mode = "attack";
      Game.notify("EnemyFound at "+ Game.time.toString(),60);
    }else{
      Memory.towersMem.mode = "heal";
    }

    //Run through the towers, picking a target if needed
    for(var towerName in towers){
      var t = towers[towerName];
      if(enemyPresent && (target===null || target.room !== t.room)){
        modStructures.pickTargets(t.room.controller, allCreepList);
      }
      modStructures.runTower(t,allCreepList);
    }
  }
};
<commit_msg>fixed unchanged var name<commit_after>//Requires for the other roles and modules

//Roles
var roleHarvester = require('role.harvester');
var roleMiner = require('role.miner');
var roleHauler = require('role.hauler');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleRepair = require('role.repair');
var roleArchitect = require('role.architect');
var roleFeeder = require('role.feeder');

//Modules
var modSpawning = require('module.spawning');
var modCommon = require('module.common');
var modStructures = require('module.structures');

//Initial memory JSON for the roles
//includes counters for roles and maxes
var initialRolesMem = {
    "numCreeps":0,
    "numHarvesters":0,
    "maxHarvesters":1,
    "numUpgraders":0,
    "maxUpgraders":0,
    "numBuilders":0,
    "maxBuilders":1,
    "numRepair":0,
    "maxRepair":1,
    "numArchitects":0,
    "betterHarvesters1":0,
    "betterHarvesters2":0,
    "numMiners":0,
    "maxMiners":0,
    "numHaulers":0,
    "maxHaulers":1,
    "numFeeders":0,
    "maxFeeders":1

};

//Tower initial memory JSON
var initialTowerMem = {
  "target":null,
  "mode":"attack",
  "fixe":null
};

//Set all the above JSONs into memeory on first start
function initialize(){
  //TODO make these per room
  Memory.roles = initialRolesMem;
  Memory.towersMem = initialTowerMem;
  Memory.initialized = true;
  Memory.conservation = false;
  Memory.fortify = false;
}

//Gets the number of living harvester Creeps
function getNumHarvesters(creepList){
  var harvesters = _.filter(creepList, (creep) => creep.memory.role == 'harvester');
  var hL = harvesters.length;
  if(Memory.roles.numHarvesters != hL){
    Memory.roles.numHarvesters = hL;
    console.log('Harvesters: ' + hL);
  }
  return hL;
}

//Gets the number of living upgrader Creeps
function getNumUpgraders(creepList){
  var upgraders = _.filter(creepList, (creep) => creep.memory.role == 'upgrader');
  var uL = upgraders.length;
  if(Memory.roles.numUpgraders != uL){
    Memory.roles.numUpgraders = uL;
    console.log('Upgraders: ' + uL);
  }
  return uL;
}

//Gets the number of living builder Creeps
function getNumBuilders(creepList){
  var builders = _.filter(creepList, (creep) => creep.memory.role == 'builder');
  var bL = builders.length;
  if(Memory.roles.numBuilders != bL){
    Memory.roles.numBuilders = bL;
    console.log('Builders: ' + bL);
  }
  return bL;
}

//Gets the number of living Repair Creeps
function getNumRepair(creepList){
  var repair = _.filter(creepList, (creep) => creep.memory.role == 'repair');
  var rL = repair.length;
  if(Memory.roles.numRepair != rL){
    Memory.roles.numRepair = rL;
    console.log('Repair: ' + rL);
  }
  return rL;
}

//Gets the number of living architect Creeps
function getNumArchitects(creepList){
  var architects = _.filter(creepList, (creep) => creep.memory.role == 'architect');
  var aL = architects.length;
  if(Memory.roles.numArchitects != aL){
    Memory.roles.numArchitects = aL;
    console.log('Architects: ' + aL);
  }
  return aL;
}

//Gets the number of living miner Creeps
function getNumMiners(creepList){
  var miners = _.filter(creepList, (creep) => creep.memory.role == 'miner');
  var mL = miners.length;
  if(Memory.roles.numMiners != mL){
    Memory.roles.numMiners = mL;
    console.log('Miners: ' + mL);
  }
  return mL;
}

//Gets the number of living hauler Creeps
function getNumHaulers(creepList){
  var haulers = _.filter(creepList, (creep) => creep.memory.role == 'hauler');
  var haulL = haulers.length;
  if(Memory.roles.numHaulers != haulL){
    Memory.roles.numHaulers = haulL;
    console.log('Haulers: ' + haulL);
  }
  return haulL;
}

function getNumFeeders(creepList){
  var feeders = _.filter(creepList, (creep) => creep.memory.role == 'feeder');
  var feedL = feeders.length;
  if(Memory.roles.numFeeders != feedL){
    Memory.roles.numFeeders = feedL;
    console.log('Haulers: ' + feedL);
  }
  return feedL;
}

//main loop
module.exports.loop = function () {

  //Only initialize if it hasnt been done (or it was manually set to false)
  if(Memory.initialized!==true){
    initialize();
  }

  //Loop to check each room that is visible to the script
  for(var roomName in Game.rooms){
    var room = Game.rooms[roomName];

    if(Memory.fortify && (!room.controller.safeMode || room.controller.safeMode<1000)){
      Memory.fortify = false;
    }

    //Creep lists in each room, comparing lengths shows if there are 'others'
    var allCreepList = room.find(FIND_CREEPS);
    var myCreepList = _.filter(allCreepList, (creep) => (creep.owner && creep.owner.username ==="PCarton"));
    var enemyPresent = allCreepList.length>myCreepList.length;

    //Al the structures in the room that are controlled by the player
    var allStructs = room.find(FIND_MY_STRUCTURES);
    var towers = _.filter(allStructs, (struct) => struct.structureType === STRUCTURE_TOWER);

    //calculates the breakdown of creeps by roles
    var h  = getNumHarvesters(myCreepList);
    var u = getNumUpgraders(myCreepList);
    var b = getNumBuilders(myCreepList);
    var r = getNumRepair(myCreepList);
    var a = getNumArchitects(myCreepList);
    var m = getNumMiners(myCreepList);
    var ha = getNumHaulers(myCreepList);
    var f = getNumFeeders(myCreepList);
    Memory.roles.numCreeps = h + u + b + r + a + m + ha + f;

    //Clear dead creeps from memory
    modCommon.clearDead();

    //assign the right run method to each creep based on its role
    for(var name in myCreepList) {
        var creep = myCreepList[name];

        //Has the non-military creeps retreat
        //Mining creeps are considered military - like the supply line
        if(enemyPresent && creep.memory.military !== true){
          modCommon.retreat(creep);
        }
        //If there are no enemies, run the appropriate role method
        else if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        else if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        else if(creep.memory.role == 'builder'){
          roleBuilder.run(creep);
        }
        else if(creep.memory.role == 'repair'){
          roleRepair.run(creep);
        }
        else if(creep.memory.role == 'architect'){
          roleArchitect.run(creep);
        }
        else if(creep.memory.role == 'miner'){
          roleMiner.run(creep);
        }
        else if(creep.memory.role == 'hauler'){
          roleHauler.run(creep);
        }
        else if(creep.memory.role == 'feeder'){
          roleFeeder.run(creep);
        }
    }

    //determine if new creeps need to be spawned and pick an appropriate spawner
    //Spawn logic is in a seperate module
    if(Memory.roles.numCreeps < modSpawning.maxCreeps){
        for(var spawn in Game.spawns){
          var spawner = Game.spawns[spawn];
          var controllerLvl= spawner.room.controller.level;
          var energyCapacity = spawner.room.energyCapacityAvailable;
          modSpawning.spawn(spawner,energyCapacity,controllerLvl);

        }
    }

    var control = room.controller;

    if(enemyPresent && modCommon.playerAttack(allCreepList) && !(control.safeMode || control.safeModeCooldown) && control.safeModeAvailable > 0 ){
      control.activateSafeMode();
      Memory.fortify = true;
      Game.notify("Activated Safe Mode");
    }

    //Variable to keep track of which enemy to shoot
    var target = Game.getObjectById(Memory.towersMem.target);

    //Notify the user on enemies or switch to healing and repairing
    if(enemyPresent){
      Memory.towersMem.mode = "attack";
      Game.notify("EnemyFound at "+ Game.time.toString(),60);
    }else{
      Memory.towersMem.mode = "heal";
    }

    //Run through the towers, picking a target if needed
    for(var towerName in towers){
      var t = towers[towerName];
      if(enemyPresent && (target===null || target.room !== t.room)){
        modStructures.pickTargets(t.room.controller, allCreepList);
      }
      modStructures.runTower(t,allCreepList);
    }
  }
};
<|endoftext|>


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

var http = require('http')
  , https = false
  , tls = false
  , url = require('url')
  , util = require('util')
  , stream = require('stream')
  , qs = require('querystring')
  ;

try {
    https = require('https');
} catch (e) {}

try {
    tls = require('tls');
} catch (e) {}

var toBase64 = function(str) {
  return (new Buffer(str || "", "ascii")).toString("base64");
};

// Hacky fix for pre-0.4.4 https
if (https && !https.Agent) {
  https.Agent = function (options) {
    http.Agent.call(this, options);
  }
  util.inherits(https.Agent, http.Agent);

  https.Agent.prototype._getConnection = function(host, port, cb) {
    var s = tls.connect(port, host, this.options, function() {
      // do other checks here?
      if (cb) cb();
    });

    return s;
  };
}

var isUrl = /^https?:/;

var globalPool = {};

var Request = function (options) {
  stream.Stream.call(this);
  this.readable = true;
  this.writable = true;

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

  for (i in options) {
    this[i] = options[i];
  }
  if (!this.pool) this.pool = globalPool;
  this.dests = [];
  this.__isRequestRequest = true;
}
util.inherits(Request, stream.Stream);
Request.prototype.getAgent = function (host, port) {
  if (!this.pool[host+':'+port]) {
    this.pool[host+':'+port] = new this.httpModule.Agent({host:host, port:port});
  }
  return this.pool[host+':'+port];
}
Request.prototype.request = function () {
  var options = this;
  if (options.url) {
    // People use this property instead all the time so why not just support it.
    options.uri = options.url;
    delete options.url;
  }

  if (!options.uri) {
    throw new Error("options.uri is a required argument");
  } else {
    if (typeof options.uri == "string") options.uri = url.parse(options.uri);
  }
  if (options.proxy) {
    if (typeof options.proxy == 'string') options.proxy = url.parse(options.proxy);
  }

  options._redirectsFollowed = options._redirectsFollowed || 0;
  options.maxRedirects = (options.maxRedirects !== undefined) ? options.maxRedirects : 10;
  options.followRedirect = (options.followRedirect !== undefined) ? options.followRedirect : true;

  options.method = options.method || 'GET';
  options.headers = options.headers || {};

  var setHost = false;
  if (!options.headers.host) {
    options.headers.host = options.uri.hostname;
    if (options.uri.port) {
      if ( !(options.uri.port === 80 && options.uri.protocol === 'http:') &&
           !(options.uri.port === 443 && options.uri.protocol === 'https:') )
      options.headers.host += (':'+options.uri.port);
    }
    setHost = true;
  }

  if (!options.uri.pathname) {options.uri.pathname = '/';}
  if (!options.uri.port) {
    if (options.uri.protocol == 'http:') {options.uri.port = 80;}
    else if (options.uri.protocol == 'https:') {options.uri.port = 443;}
  }

  if (options.bodyStream || options.responseBodyStream) {
    console.error('options.bodyStream and options.responseBodyStream is deprecated. You should now send the request object to stream.pipe()');
    this.pipe(options.responseBodyStream || options.bodyStream)
  }

  if (options.proxy) {
    options.port = options.proxy.port;
    options.host = options.proxy.hostname;
  } else {
    options.port = options.uri.port;
    options.host = options.uri.hostname;
  }

  if (options.onResponse === true) {
    options.onResponse = options.callback;
    delete options.callback;
  }

  var clientErrorHandler = function (error) {
    if (setHost) delete options.headers.host;
    options.emit('error', error);
  };
  if (options.onResponse) options.on('error', function (e) {options.onResponse(e)});
  if (options.callback) options.on('error', function (e) {options.callback(e)});

  if (options.uri.auth && !options.headers.authorization) {
    options.headers.authorization = "Basic " + toBase64(options.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':'));
  }
  if (options.proxy && options.proxy.auth && !options.headers['proxy-authorization']) {
    options.headers.authorization = "Basic " + toBase64(options.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':'));
  }

  options.path = options.uri.href.replace(options.uri.protocol + '//' + options.uri.host, '');
  if (options.path.length === 0) options.path = '/';

  if (options.proxy) options.path = (options.uri.protocol + '//' + options.uri.host + options.path);

  if (options.json) {
    options.headers['content-type'] = 'application/json';
    options.body = JSON.stringify(options.json);
  } else if (options.multipart) {
    options.body = '';
    options.headers['content-type'] = 'multipart/related;boundary="frontier"';

    if (!options.multipart.forEach) throw new Error('Argument error, options.multipart.');
    options.multipart.forEach(function (part) {
      var body = part.body;
      if(!body) throw Error('Body attribute missing in multipart.');
      delete part.body;
      options.body += '--frontier\r\n';
      Object.keys(part).forEach(function(key){
        options.body += key + ': ' + part[key] + '\r\n'
      })
      options.body += '\r\n' + body + '\r\n';
    })
    options.body += '--frontier--'
  }

  if (options.body) {
    if (!Buffer.isBuffer(options.body)) {
      options.body = new Buffer(options.body);
    }
    if (options.body.length) {
      options.headers['content-length'] = options.body.length;
    } else {
      throw new Error('Argument error, options.body.');
    }
  }

  options.httpModule =
    {"http:":http, "https:":https}[options.proxy ? options.proxy.protocol : options.uri.protocol]

  if (!options.httpModule) throw new Error("Invalid protocol");

  if (options.pool === false) {
    options.agent = false;
  } else {
    if (options.maxSockets) {
      options.agent = options.getAgent(options.host, options.port);
      options.agent.maxSockets = options.maxSockets;
    }
    if (options.pool.maxSockets) {
      options.agent = options.getAgent(options.host, options.port);
      options.agent.maxSockets = options.pool.maxSockets;
    }
  }

  options.start = function () {
    options._started = true;
    options.req = options.httpModule.request(options, function (response) {
      options.response = response;
      if (setHost) delete options.headers.host;

      if (response.statusCode >= 300 &&
          response.statusCode < 400  &&
          options.followRedirect     &&
          options.method !== 'PUT' &&
          options.method !== 'POST' &&
          response.headers.location) {
        if (options._redirectsFollowed >= options.maxRedirects) {
          options.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop."));
        }
        options._redirectsFollowed += 1;
        if (!isUrl.test(response.headers.location)) {
          response.headers.location = url.resolve(options.uri.href, response.headers.location);
        }
        options.uri = response.headers.location;
        delete options.req;
        delete options.agent;
        delete options._started;
        if (options.headers) {
          delete options.headers.host;
        }
        request(options, options.callback);
        return; // Ignore the rest of the response
      } else {
        options._redirectsFollowed = 0;
        // Be a good stream and emit end when the response is finished.
        // Hack to emit end on close because of a core bug that never fires end
        response.on('close', function () {options.response.emit('end')})

        if (options.encoding) {
          if (options.dests.length !== 0) {
            console.error("Ingoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.");
          } else {
            response.setEncoding(options.encoding);
          }
        }

        options.dests.forEach(function (dest) {
          if (dest.headers) {
            dest.headers['content-type'] = response.headers['content-type'];
            if (response.headers['content-length']) {
              dest.headers['content-length'] = response.headers['content-length'];
            }
          }
        })

        response.on("data", function (chunk) {options.emit("data", chunk)});
        response.on("end", function (chunk) {options.emit("end", chunk)});
        response.on("close", function () {options.emit("close")});

        if (options.onResponse) {
          options.onResponse(null, response);
        }
        if (options.callback) {
          var buffer = '';
          options.on("data", function (chunk) {
            buffer += chunk;
          })
          options.on("end", function () {
            options.callback(null, response, buffer);
          })
          ;
        }
      }
    })

    options.req.on('error', clientErrorHandler);
  }

  options.once('pipe', function (src) {
    if (options.ntick) throw new Error("You cannot pipe to this stream after the first nextTick() after creation of the request stream.")
    options.src = src;
    options.on('pipe', function () {
      console.error("You have already piped to this stream. Pipeing twice is likely to break the request.")
    })
  })

  process.nextTick(function () {
    if (options.body) {
      options.write(options.body);
      options.end();
    } else if (options.requestBodyStream) {
      console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.")
      options.requestBodyStream.pipe(options);
    } else if (!options.src) {
      options.end();
    }
    options.ntick = true;
  })
}
Request.prototype.pipe = function (dest) {
  if (this.response) throw new Error("You cannot pipe after the response event.")
  this.dests.push(dest);
  stream.Stream.prototype.pipe.call(this, dest)
}
Request.prototype.write = function () {
  if (!this._started) this.start();
  if (!this.req) throw new Error("This request has been piped before http.request() was called.");
  this.req.write.apply(this.req, arguments);
}
Request.prototype.end = function () {
  if (!this._started) this.start();
  if (!this.req) throw new Error("This request has been piped before http.request() was called.");
  this.req.end.apply(this.req, arguments);
}
Request.prototype.pause = function () {
  if (!this.response) throw new Error("This request has been piped before http.request() was called.");
  this.response.pause.apply(this.response, arguments);
}
Request.prototype.resume = function () {
  if (!this.response) throw new Error("This request has been piped before http.request() was called.");
  this.response.resume.apply(this.response, arguments);
}

function request (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  if (callback) options.callback = callback;
  var r = new Request(options);
  r.request();
  return r;
}

module.exports = request;

request.defaults = function (options) {
  var def = function (method) {
    var d = function (opts, callback) {
      for (i in options) {
        if (opts[i] === undefined) opts[i] = options[i];
      }
      return method(opts, callback);
    }
    return d;
  }
  de = def(request);
  de.get = def(request.get);
  de.post = def(request.post);
  de.put = def(request.put);
  de.head = def(request.head);
  de.del = def(request.del);
  return de;
}

request.get = request;
request.post = function (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  options.method = 'POST';
  return request(options, callback);
};
request.put = function (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  options.method = 'PUT';
  return request(options, callback);
};
request.head = function (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  options.method = 'HEAD';
  if (options.body || options.requestBodyStream || options.json || options.multipart) {
    throw new Error("HTTP HEAD requests MUST NOT include a request body.");
  }
  return request(options, callback);
};
request.del = function (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  options.method = 'DELETE';
  return request(options, callback);
}
<commit_msg>Fixing for node http client refactor.<commit_after>// Copyright 2010-2011 Mikeal Rogers
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

var http = require('http')
  , https = false
  , tls = false
  , url = require('url')
  , util = require('util')
  , stream = require('stream')
  , qs = require('querystring')
  ;

try {
    https = require('https');
} catch (e) {}

try {
    tls = require('tls');
} catch (e) {}

var toBase64 = function(str) {
  return (new Buffer(str || "", "ascii")).toString("base64");
};

// Hacky fix for pre-0.4.4 https
if (https && !https.Agent) {
  https.Agent = function (options) {
    http.Agent.call(this, options);
  }
  util.inherits(https.Agent, http.Agent);

  https.Agent.prototype._getConnection = function(host, port, cb) {
    var s = tls.connect(port, host, this.options, function() {
      // do other checks here?
      if (cb) cb();
    });

    return s;
  };
}

var isUrl = /^https?:/;

var globalPool = {};

var Request = function (options) {
  stream.Stream.call(this);
  this.readable = true;
  this.writable = true;

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

  for (i in options) {
    this[i] = options[i];
  }
  if (!this.pool) this.pool = globalPool;
  this.dests = [];
  this.__isRequestRequest = true;
}
util.inherits(Request, stream.Stream);
Request.prototype.getAgent = function (host, port) {
  if (!this.pool[host+':'+port]) {
    this.pool[host+':'+port] = new this.httpModule.Agent({host:host, port:port});
  }
  return this.pool[host+':'+port];
}
Request.prototype.request = function () {
  var options = this;
  if (options.url) {
    // People use this property instead all the time so why not just support it.
    options.uri = options.url;
    delete options.url;
  }

  if (!options.uri) {
    throw new Error("options.uri is a required argument");
  } else {
    if (typeof options.uri == "string") options.uri = url.parse(options.uri);
  }
  if (options.proxy) {
    if (typeof options.proxy == 'string') options.proxy = url.parse(options.proxy);
  }

  options._redirectsFollowed = options._redirectsFollowed || 0;
  options.maxRedirects = (options.maxRedirects !== undefined) ? options.maxRedirects : 10;
  options.followRedirect = (options.followRedirect !== undefined) ? options.followRedirect : true;

  options.method = options.method || 'GET';
  options.headers = options.headers || {};

  var setHost = false;
  if (!options.headers.host) {
    options.headers.host = options.uri.hostname;
    if (options.uri.port) {
      if ( !(options.uri.port === 80 && options.uri.protocol === 'http:') &&
           !(options.uri.port === 443 && options.uri.protocol === 'https:') )
      options.headers.host += (':'+options.uri.port);
    }
    setHost = true;
  }

  if (!options.uri.pathname) {options.uri.pathname = '/';}
  if (!options.uri.port) {
    if (options.uri.protocol == 'http:') {options.uri.port = 80;}
    else if (options.uri.protocol == 'https:') {options.uri.port = 443;}
  }

  if (options.bodyStream || options.responseBodyStream) {
    console.error('options.bodyStream and options.responseBodyStream is deprecated. You should now send the request object to stream.pipe()');
    this.pipe(options.responseBodyStream || options.bodyStream)
  }

  if (options.proxy) {
    options.port = options.proxy.port;
    options.host = options.proxy.hostname;
  } else {
    options.port = options.uri.port;
    options.host = options.uri.hostname;
  }

  if (options.onResponse === true) {
    options.onResponse = options.callback;
    delete options.callback;
  }

  var clientErrorHandler = function (error) {
    if (setHost) delete options.headers.host;
    options.emit('error', error);
  };
  if (options.onResponse) options.on('error', function (e) {options.onResponse(e)});
  if (options.callback) options.on('error', function (e) {options.callback(e)});

  if (options.uri.auth && !options.headers.authorization) {
    options.headers.authorization = "Basic " + toBase64(options.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':'));
  }
  if (options.proxy && options.proxy.auth && !options.headers['proxy-authorization']) {
    options.headers.authorization = "Basic " + toBase64(options.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':'));
  }

  options.path = options.uri.href.replace(options.uri.protocol + '//' + options.uri.host, '');
  if (options.path.length === 0) options.path = '/';

  if (options.proxy) options.path = (options.uri.protocol + '//' + options.uri.host + options.path);

  if (options.json) {
    options.headers['content-type'] = 'application/json';
    options.body = JSON.stringify(options.json);
  } else if (options.multipart) {
    options.body = '';
    options.headers['content-type'] = 'multipart/related;boundary="frontier"';

    if (!options.multipart.forEach) throw new Error('Argument error, options.multipart.');
    options.multipart.forEach(function (part) {
      var body = part.body;
      if(!body) throw Error('Body attribute missing in multipart.');
      delete part.body;
      options.body += '--frontier\r\n';
      Object.keys(part).forEach(function(key){
        options.body += key + ': ' + part[key] + '\r\n'
      })
      options.body += '\r\n' + body + '\r\n';
    })
    options.body += '--frontier--'
  }

  if (options.body) {
    if (!Buffer.isBuffer(options.body)) {
      options.body = new Buffer(options.body);
    }
    if (options.body.length) {
      options.headers['content-length'] = options.body.length;
    } else {
      throw new Error('Argument error, options.body.');
    }
  }

  options.httpModule =
    {"http:":http, "https:":https}[options.proxy ? options.proxy.protocol : options.uri.protocol]

  if (!options.httpModule) throw new Error("Invalid protocol");

  if (options.pool === false) {
    options.agent = false;
  } else {
    if (options.maxSockets) {
      // Don't use our pooling if node has the refactored client
      options.agent = options.httpModule.globalAgent || options.getAgent(options.host, options.port);
      options.agent.maxSockets = options.maxSockets;
    }
    if (options.pool.maxSockets) {
      // Don't use our pooling if node has the refactored client
      options.agent = options.httpModule.globalAgent || options.getAgent(options.host, options.port);
      options.agent.maxSockets = options.pool.maxSockets;
    }
  }

  options.start = function () {
    options._started = true;
    options.req = options.httpModule.request(options, function (response) {
      options.response = response;
      if (setHost) delete options.headers.host;

      if (response.statusCode >= 300 &&
          response.statusCode < 400  &&
          options.followRedirect     &&
          options.method !== 'PUT' &&
          options.method !== 'POST' &&
          response.headers.location) {
        if (options._redirectsFollowed >= options.maxRedirects) {
          options.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop."));
        }
        options._redirectsFollowed += 1;
        if (!isUrl.test(response.headers.location)) {
          response.headers.location = url.resolve(options.uri.href, response.headers.location);
        }
        options.uri = response.headers.location;
        delete options.req;
        delete options.agent;
        delete options._started;
        if (options.headers) {
          delete options.headers.host;
        }
        request(options, options.callback);
        return; // Ignore the rest of the response
      } else {
        options._redirectsFollowed = 0;
        // Be a good stream and emit end when the response is finished.
        // Hack to emit end on close because of a core bug that never fires end
        response.on('close', function () {options.response.emit('end')})

        if (options.encoding) {
          if (options.dests.length !== 0) {
            console.error("Ingoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.");
          } else {
            response.setEncoding(options.encoding);
          }
        }

        options.dests.forEach(function (dest) {
          if (dest.headers) {
            dest.headers['content-type'] = response.headers['content-type'];
            if (response.headers['content-length']) {
              dest.headers['content-length'] = response.headers['content-length'];
            }
          }
        })

        response.on("data", function (chunk) {options.emit("data", chunk)});
        response.on("end", function (chunk) {options.emit("end", chunk)});
        response.on("close", function () {options.emit("close")});

        if (options.onResponse) {
          options.onResponse(null, response);
        }
        if (options.callback) {
          var buffer = '';
          options.on("data", function (chunk) {
            buffer += chunk;
          })
          options.on("end", function () {
            options.callback(null, response, buffer);
          })
          ;
        }
      }
    })

    options.req.on('error', clientErrorHandler);
  }

  options.once('pipe', function (src) {
    if (options.ntick) throw new Error("You cannot pipe to this stream after the first nextTick() after creation of the request stream.")
    options.src = src;
    options.on('pipe', function () {
      console.error("You have already piped to this stream. Pipeing twice is likely to break the request.")
    })
  })

  process.nextTick(function () {
    if (options.body) {
      options.write(options.body);
      options.end();
    } else if (options.requestBodyStream) {
      console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.")
      options.requestBodyStream.pipe(options);
    } else if (!options.src) {
      options.end();
    }
    options.ntick = true;
  })
}
Request.prototype.pipe = function (dest) {
  if (this.response) throw new Error("You cannot pipe after the response event.")
  this.dests.push(dest);
  stream.Stream.prototype.pipe.call(this, dest)
}
Request.prototype.write = function () {
  if (!this._started) this.start();
  if (!this.req) throw new Error("This request has been piped before http.request() was called.");
  this.req.write.apply(this.req, arguments);
}
Request.prototype.end = function () {
  if (!this._started) this.start();
  if (!this.req) throw new Error("This request has been piped before http.request() was called.");
  this.req.end.apply(this.req, arguments);
}
Request.prototype.pause = function () {
  if (!this.response) throw new Error("This request has been piped before http.request() was called.");
  this.response.pause.apply(this.response, arguments);
}
Request.prototype.resume = function () {
  if (!this.response) throw new Error("This request has been piped before http.request() was called.");
  this.response.resume.apply(this.response, arguments);
}

function request (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  if (callback) options.callback = callback;
  var r = new Request(options);
  r.request();
  return r;
}

module.exports = request;

request.defaults = function (options) {
  var def = function (method) {
    var d = function (opts, callback) {
      for (i in options) {
        if (opts[i] === undefined) opts[i] = options[i];
      }
      return method(opts, callback);
    }
    return d;
  }
  de = def(request);
  de.get = def(request.get);
  de.post = def(request.post);
  de.put = def(request.put);
  de.head = def(request.head);
  de.del = def(request.del);
  return de;
}

request.get = request;
request.post = function (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  options.method = 'POST';
  return request(options, callback);
};
request.put = function (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  options.method = 'PUT';
  return request(options, callback);
};
request.head = function (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  options.method = 'HEAD';
  if (options.body || options.requestBodyStream || options.json || options.multipart) {
    throw new Error("HTTP HEAD requests MUST NOT include a request body.");
  }
  return request(options, callback);
};
request.del = function (options, callback) {
  if (typeof options === 'string') options = {uri:options};
  options.method = 'DELETE';
  return request(options, callback);
}
<|endoftext|>


<commit_before>"use-strict"
var hbjs = require("handbrake-js"),
	chokidar = require("chokidar"),
	path = require("path"),
	fs = require("fs");

function SEU(path) {
	if (!(this instanceof SEU)) {
		throw new Error("SEU should be created with `new`")
	};
	console.log("Initiating in", path);
	this.paths = {
		encode: `${path}/encode`,
		encoded: `${path}/encoded`,
		encoding: `${path}/encoding`,
		upload: `${path}/upload`,
		uploaded: `${path}/uploaded`
	};
	Object.keys(this.paths).forEach(dir => {
		let p = this.paths[dir];
		if (!fs.existsSync(p)){
			fs.mkdirSync(p);
		}
	});
}

SEU.prototype.Watch = function(){
	console.log("Started.");
	this.encode = chokidar.watch(this.paths.encode, { ignored: /[\/\\]\./, persistent: true });
	this.upload = chokidar.watch(this.paths.upload, { ignored: /[\/\\]\./, persistent: true });
	this.encode.on('add', filePath => {
		var p = path.parse(filePath);
		var options = {
			input: filePath,
			output: path.normalize(`${this.paths.encoding}/${p.name}.mp4`),
			encoder: "x264",
			"encoder-preset": "Slow",
			quality: 22,
			audio: 1,
			aencoder: "copy:aac",
			ab: "192",
			mixdown: "stereo",
			arate: "44.1",
			subtitle: "1",
			"subtitle-burned": 1,
			optimize: true
		};
		this.Encode(options);
	});
	this.upload.on('add', filePath => {
		this.Upload(filePath);
	});
}

SEU.prototype.Encode = function(options){
	console.log("Settings Used:", options);
	hbjs.spawn(options)
		.on("output", (stdout, stderr) => {
			// some shit
		})
		.on("error", err => {
			throw err;
			// invalid user input, no video found etc
		})
		.on("progress", progress => {
			var log = `${progress.task}:`;
			switch(progress.task){
				case "Encoding":
					log = `${log} ${progress.taskNumber} of ${progress.taskCount}, ` +
					`${progress.percentComplete}% (${progress.fps} fps, avg ${progress.avgFps} fps,` +
					` ETA: ${progress.eta})`;
					break;
				case "Muxing":
					log = `${log} ${progress.percentComplete}%... This might take a while.`;
					break;
			}
			try{
				process.stdout.clearLine();
				process.stdout.cursorTo(0);
				process.stdout.write(log);
			}catch(e){
				// Fuck you pm2
				console.log(log);
			}
		})
		.on("complete", () => {
			try{
				//process.stdout.clearLine();
				//process.stdout.cursorTo(0);
				process.stdout.write("\n");
			}catch(e){
				// Fuck you pm2
			}
			var p = path.parse(options.input);
			fs.rename(options.input, path.normalize(`${this.paths.encoded}/${p.base}`), err => {
				if(err) throw err;
			});
			var p = path.parse(options.output);
			fs.rename(options.output, path.normalize(`${this.paths.upload}/${p.base}`), err => {
				if(err) throw err;
			});
		});
}

SEU.prototype.Upload = function(filePath){
	console.log("%s, is ready for upload.", filePath);
	// TODO upload api stuff
}

module.exports = SEU;
<commit_msg>add config stuff<commit_after>"use-strict"
var hbjs = require("handbrake-js"),
	chokidar = require("chokidar"),
	path = require("path"),
	fs = require("fs");

function SEU(path) {
	if (!(this instanceof SEU)) {
		throw new Error("SEU should be created with `new`")
	};
	console.log("Initiating in", path);
	this.paths = {
		dirs: {
			root: path,
			encode: `${path}/encode`,
			encoded: `${path}/encoded`,
			encoding: `${path}/encoding`,
			upload: `${path}/upload`,
			uploaded: `${path}/uploaded`,
			config: `${path}/config`
		},
		files: {
			config: `${path}/config/settings.json`
		}
	};
	Object.keys(this.paths.dirs).forEach(dir => {
		let p = this.paths.dirs[dir];
		if (!fs.existsSync(p)){
			fs.mkdir(p, err => {
				if(err){
					throw err;
				}
			});
		}
	});
	this.createConfig();
}

SEU.prototype.createConfig = function(){
	var settings = {
		extension: "mp4",
		options: {
			encoder: "x264",
			"encoder-preset": "Slow",
			quality: 22,
			audio: 1,
			aencoder: "copy:aac",
			ab: "192",
			mixdown: "stereo",
			arate: "44.1",
			subtitle: "1",
			"subtitle-burned": 1,
			optimize: true
		}
	};
	if (!fs.existsSync(this.paths.files.config)){
		fs.writeFile(this.paths.files.config, JSON.stringify(settings), err => {
			if(err) {
				throw err;
			}
		});
		console.log(`Config file created in ${this.paths.files.config}\n please modify according to the settings you want and run again.`);
		process.exit();
	}
}

SEU.prototype.loadConfig = function(filePath){
	fs.readFile(filePath, 'utf8', (err, data) => {
		if (err) throw err;
		this.settings = JSON.parse(data);
	});
}

SEU.prototype.Watch = function(){
	console.log("Started.");
	this.encode = chokidar.watch(this.paths.dirs.encode, { ignored: /[\/\\]\./, persistent: true });
	this.upload = chokidar.watch(this.paths.dirs.upload, { ignored: /[\/\\]\./, persistent: true });
	this.config = chokidar.watch(this.paths.files.config, { ignored: /[\/\\]\./, persistent: true });
	this.encode.on('add', filePath => {
		this.Encode(filePath);
	});
	this.upload.on('add', filePath => {
		this.Upload(filePath);
	});
	this.config.on('add', filePath => {
		this.loadConfig(filePath);
	}).on('modify', filePath => {
		this.loadConfig(filePath);
	});
}

SEU.prototype.Encode = function(filePath){
	var p = path.parse(filePath);
	var options = {
		input: filePath,
		output: path.normalize(`${this.paths.dirs.encoding}/${p.name}.${this.settings.extension}`),
	}
	options = Object.assign(options, this.settings.options);
	console.log("Settings Used:", options);
	hbjs.spawn(options)
		.on("output", (stdout, stderr) => {
			// some shit
		})
		.on("error", err => {
			throw err;
			// invalid user input, no video found etc
		})
		.on("progress", progress => {
			var log = `${progress.task}:`;
			switch(progress.task){
				case "Encoding":
					log = `${log} ${progress.taskNumber} of ${progress.taskCount}, ` +
					`${progress.percentComplete}% (${progress.fps} fps, avg ${progress.avgFps} fps,` +
					` ETA: ${progress.eta})`;
					break;
				case "Muxing":
					log = `${log} ${progress.percentComplete}%... This might take a while.`;
					break;
			}
			try{
				process.stdout.clearLine();
				process.stdout.cursorTo(0);
				process.stdout.write(log);
			}catch(e){
				// Fuck you pm2
				console.log(log);
			}
		})
		.on("complete", () => {
			try{
				//process.stdout.clearLine();
				//process.stdout.cursorTo(0);
				process.stdout.write("\n");
			}catch(e){
				// Fuck you pm2
			}
			var p = path.parse(options.input);
			fs.rename(options.input, path.normalize(`${this.paths.dirs.encoded}/${p.base}`), err => {
				if(err) throw err;
			});
			var p = path.parse(options.output);
			fs.rename(options.output, path.normalize(`${this.paths.dirs.upload}/${p.base}`), err => {
				if(err) throw err;
			});
		});
}

SEU.prototype.Upload = function(filePath){
	console.log("%s, is ready for upload.", filePath);
	// TODO upload api stuff
}

module.exports = SEU;
<|endoftext|>