<commit_before>var child_process = require('child_process'),
    path = require('path'),
    fs = require('fs'),
    constants = process.ENOENT ? process : require('constants'),
    glob = require('glob'),
    request = require('request'),
    _ = require('underscore'),
    seq = require('seq'),
    urlTools = require('./util/urlTools'),
    fsTools = require('./util/fsTools'),
    error = require('./util/error'),
    assets = require('./assets');

require('bufferjs');

function AssetConfigResolver(config) {
    _.extend(this, config || {});
    if (!/^[^:]+:/.test(this.root)) { // No protocol?
        this.root = urlTools.fsDirToFileUrl(this.root || process.cwd());
    }
    this.protocols = this.protocols || {};
};

AssetConfigResolver.prototype.resolve = function (assetConfig, fromUrl, cb) {
    var that = this;
    if (_.isArray(assetConfig)) {
        // Call ourselves recursively for each item, flatten the results and report back
        return seq.ap(assetConfig)
            .parMap(function (_assetConfig) {
                that.resolve(_assetConfig, fromUrl, this);
            })
            .seq(function () {
                cb(null, _.flatten(this.stack));
            })
            ['catch'](cb);
    }
    if (typeof assetConfig === 'string') {
        if (/^\//.test(assetConfig) && /^file:/.test(fromUrl) && /^file:/.test(that.root)) {
            assetConfig = {url: that.root + assetConfig.substr(1)};
        } else {
            assetConfig = {url: urlTools.resolveUrl(fromUrl, assetConfig)};
        }
    }
    if (assetConfig.url) {
        var protocol = assetConfig.url.substr(0, assetConfig.url.indexOf(':')),
            pathname = assetConfig.url.replace(/^\w+:(?:\/\/)?/, ""); // Strip protocol and two leading slashes if present
        if (protocol === 'file') {
            if (/[\*\?]/.test(pathname)) {
                // Expand wildcard, then expand each resulting url
                return glob.glob(pathname, error.passToFunction(cb, function (fsPaths) {
                    if (!fsPaths.length) {
                        cb(new Error("AssetGraph.resolveAssetConfig: Wildcard " + pathname + " expanded to nothing"));
                    } else {
                        that.resolve(fsPaths.map(function (fsPath) {
                            return 'file://' + fsPath;
                        }), fromUrl, cb);
                    }
                }));
            }
            assetConfig.rawSrcProxy = function (cb) {
                fs.readFile(pathname, null, cb);
            };
        } else if (protocol === 'http' || protocol === 'https') {
            assetConfig.rawSrcProxy = function (cb) {
                request({
                    url: assetConfig.url,
                    onResponse: true
                }, error.passToFunction(cb, function (response) {
                    if (response.statusCode >= 400) {
                        cb(new Error("Got " + response.statusCode + " from remote server: " + assetConfig.url));
                    } else {
                        var metadata = {},
                            buffers = [];
                        if ('content-type' in response.headers) {
                            var matchContentType = response.headers['content-type'].match(/^\s*([\w\/\-]+)\s*(?:;\s*charset=([\'\"]|)\s*([\w\-]+)\s*\2\s*)?$/i);
                            if (matchContentType) {
                                metadata.contentType = matchContentType[1].toLowerCase();
                                if (matchContentType[3]) {
                                    metadata.originalEncoding = matchContentType[3].toLowerCase();
                                }
                            } else {
                                console.log("AssetConfigResolver: Couldn't parse Content-Type " + response.headers['content-type'] + " while fetching " + assetConfig.url);
                            }
                        }
                        response.on('data', function (buffer) {
                            buffers.push(buffer);
                        }).on('end', function () {
                            cb(null, Buffer.concat(buffers), metadata);
                        }).on('error', cb);
                    }
               }));
            };
        } else if (protocol === 'data') {
            var dataUrlMatch = pathname.match(/^([\w\/\-]+)(?:;charset=([\w\/\-]+))?(;base64)?,(.*)$/);
            if (dataUrlMatch) {
                var contentType = dataUrlMatch[1];
                if (dataUrlMatch[2]) {
                    assetConfig.originalEncoding = dataUrlMatch[2];
                }
                if (dataUrlMatch[3]) {
                    assetConfig.rawSrc = new Buffer(dataUrlMatch[4], 'base64');
                } else {
                    assetConfig.rawSrc = new Buffer(dataUrlMatch[4], 'binary'); // FIXME: support percent-encoded bytes?
                }
                assetConfig.contentType = assetConfig.contentType || contentType;
            } else {
                cb(new Error("Cannot parse data url: " + assetConfig.url));
            }
        } else if (protocol in this.protocols) {
            return that.protocols[protocol].resolve(pathname, error.passToFunction(cb, function (resolvedAssetConfigs) {
                // Reresolve
                that.resolve(resolvedAssetConfigs, fromUrl, cb);
            }));
        } else if (/^file:/.test(fromUrl)) {
            return fsTools.findParentDirCached(urlTools.fileUrlToFsPath(fromUrl), protocol, error.passToFunction(cb, function (parentPath) {
                assetConfig.url = urlTools.fsFilePathToFileUrl(parentPath + '/' + pathname);
                // Reresolve
                that.resolve(assetConfig, fromUrl, cb);
            }));
        } else {
            return cb(new Error("Cannot resolve assetConfig url: " + assetConfig.url));
        }
        if (!assetConfig.type) {
            if (assetConfig.contentType) {
                assetConfig.type = assets.lookupContentType(assetConfig.contentType);
            } else {
                var extension = path.extname(assetConfig.url.replace(/\?.*$/, ""));
                if (extension in assets.typeByExtension) {
                    assetConfig.type = assets.typeByExtension[extension];
                } else {
                    // Looks like there's no way around loading the asset and looking at the src or HTTP headers
                    return assetConfig.rawSrcProxy(function (err, src, metadata) {
                        if (err) {
                            if (err.errno === constants.EISDIR || err.errno === constants.EINVAL) {
                                assetConfig.url += /\/$/.test(assetConfig.url) ? 'index.html' : '/index.html';
                                delete assetConfig.rawSrcProxy;
                                return that.resolve(assetConfig, fromUrl, cb);
                            } else {
                                return cb(err);
                            }
                        }
                        function foundType(type) {
                            assetConfig.rawSrc = src;
                            assetConfig.type = type;
                            cb(null, assetConfig);
                        }
                        if (metadata && metadata.contentType) {
                            // If the asset was served using HTTP, we shouldn't try to second guess by sniffing.
                            foundType(assets.lookupContentType(metadata.contentType));
                        } else {
                            // Work the magic
                            var fileProcess = child_process.spawn('file', ['-b', '--mime-type', '-']),
                                fileOutput = '';
                            fileProcess.stdout.on('data', function (chunk) {
                                fileOutput += chunk;
                            }).on('end', function () {
                                foundType(assets.lookupContentType(fileOutput.match(/^([^\n]*)/)[1]));
                            });
                            fileProcess.stdin.write(src);
                            fileProcess.stdin.end();
                        }
                    });
                }
            }
        }
    }
    cb(null, assetConfig);
};

module.exports = AssetConfigResolver;
<commit_msg>AssetConfigResolver: Remove fragment identifier from the url before looking for the extension.<commit_after>var child_process = require('child_process'),
    path = require('path'),
    fs = require('fs'),
    constants = process.ENOENT ? process : require('constants'),
    glob = require('glob'),
    request = require('request'),
    _ = require('underscore'),
    seq = require('seq'),
    urlTools = require('./util/urlTools'),
    fsTools = require('./util/fsTools'),
    error = require('./util/error'),
    assets = require('./assets');

require('bufferjs');

function AssetConfigResolver(config) {
    _.extend(this, config || {});
    if (!/^[^:]+:/.test(this.root)) { // No protocol?
        this.root = urlTools.fsDirToFileUrl(this.root || process.cwd());
    }
    this.protocols = this.protocols || {};
};

AssetConfigResolver.prototype.resolve = function (assetConfig, fromUrl, cb) {
    var that = this;
    if (_.isArray(assetConfig)) {
        // Call ourselves recursively for each item, flatten the results and report back
        return seq.ap(assetConfig)
            .parMap(function (_assetConfig) {
                that.resolve(_assetConfig, fromUrl, this);
            })
            .seq(function () {
                cb(null, _.flatten(this.stack));
            })
            ['catch'](cb);
    }
    if (typeof assetConfig === 'string') {
        if (/^\//.test(assetConfig) && /^file:/.test(fromUrl) && /^file:/.test(that.root)) {
            assetConfig = {url: that.root + assetConfig.substr(1)};
        } else {
            assetConfig = {url: urlTools.resolveUrl(fromUrl, assetConfig)};
        }
    }
    if (assetConfig.url) {
        var protocol = assetConfig.url.substr(0, assetConfig.url.indexOf(':')),
            pathname = assetConfig.url.replace(/^\w+:(?:\/\/)?/, ""); // Strip protocol and two leading slashes if present
        if (protocol === 'file') {
            if (/[\*\?]/.test(pathname)) {
                // Expand wildcard, then expand each resulting url
                return glob.glob(pathname, error.passToFunction(cb, function (fsPaths) {
                    if (!fsPaths.length) {
                        cb(new Error("AssetGraph.resolveAssetConfig: Wildcard " + pathname + " expanded to nothing"));
                    } else {
                        that.resolve(fsPaths.map(function (fsPath) {
                            return 'file://' + fsPath;
                        }), fromUrl, cb);
                    }
                }));
            }
            assetConfig.rawSrcProxy = function (cb) {
                fs.readFile(pathname, null, cb);
            };
        } else if (protocol === 'http' || protocol === 'https') {
            assetConfig.rawSrcProxy = function (cb) {
                request({
                    url: assetConfig.url,
                    onResponse: true
                }, error.passToFunction(cb, function (response) {
                    if (response.statusCode >= 400) {
                        cb(new Error("Got " + response.statusCode + " from remote server: " + assetConfig.url));
                    } else {
                        var metadata = {},
                            buffers = [];
                        if ('content-type' in response.headers) {
                            var matchContentType = response.headers['content-type'].match(/^\s*([\w\/\-]+)\s*(?:;\s*charset=([\'\"]|)\s*([\w\-]+)\s*\2\s*)?$/i);
                            if (matchContentType) {
                                metadata.contentType = matchContentType[1].toLowerCase();
                                if (matchContentType[3]) {
                                    metadata.originalEncoding = matchContentType[3].toLowerCase();
                                }
                            } else {
                                console.log("AssetConfigResolver: Couldn't parse Content-Type " + response.headers['content-type'] + " while fetching " + assetConfig.url);
                            }
                        }
                        response.on('data', function (buffer) {
                            buffers.push(buffer);
                        }).on('end', function () {
                            cb(null, Buffer.concat(buffers), metadata);
                        }).on('error', cb);
                    }
               }));
            };
        } else if (protocol === 'data') {
            var dataUrlMatch = pathname.match(/^([\w\/\-]+)(?:;charset=([\w\/\-]+))?(;base64)?,(.*)$/);
            if (dataUrlMatch) {
                var contentType = dataUrlMatch[1];
                if (dataUrlMatch[2]) {
                    assetConfig.originalEncoding = dataUrlMatch[2];
                }
                if (dataUrlMatch[3]) {
                    assetConfig.rawSrc = new Buffer(dataUrlMatch[4], 'base64');
                } else {
                    assetConfig.rawSrc = new Buffer(dataUrlMatch[4], 'binary'); // FIXME: support percent-encoded bytes?
                }
                assetConfig.contentType = assetConfig.contentType || contentType;
            } else {
                cb(new Error("Cannot parse data url: " + assetConfig.url));
            }
        } else if (protocol in this.protocols) {
            return that.protocols[protocol].resolve(pathname, error.passToFunction(cb, function (resolvedAssetConfigs) {
                // Reresolve
                that.resolve(resolvedAssetConfigs, fromUrl, cb);
            }));
        } else if (/^file:/.test(fromUrl)) {
            return fsTools.findParentDirCached(urlTools.fileUrlToFsPath(fromUrl), protocol, error.passToFunction(cb, function (parentPath) {
                assetConfig.url = urlTools.fsFilePathToFileUrl(parentPath + '/' + pathname);
                // Reresolve
                that.resolve(assetConfig, fromUrl, cb);
            }));
        } else {
            return cb(new Error("Cannot resolve assetConfig url: " + assetConfig.url));
        }
        if (!assetConfig.type) {
            if (assetConfig.contentType) {
                assetConfig.type = assets.lookupContentType(assetConfig.contentType);
            } else {
                var extension = path.extname(assetConfig.url.replace(/[\?\#].*$/, ""));
                if (extension in assets.typeByExtension) {
                    assetConfig.type = assets.typeByExtension[extension];
                } else {
                    // Looks like there's no way around loading the asset and looking at the src or HTTP headers
                    return assetConfig.rawSrcProxy(function (err, src, metadata) {
                        if (err) {
                            if (err.errno === constants.EISDIR || err.errno === constants.EINVAL) {
                                assetConfig.url += /\/$/.test(assetConfig.url) ? 'index.html' : '/index.html';
                                delete assetConfig.rawSrcProxy;
                                return that.resolve(assetConfig, fromUrl, cb);
                            } else {
                                return cb(err);
                            }
                        }
                        function foundType(type) {
                            assetConfig.rawSrc = src;
                            assetConfig.type = type;
                            cb(null, assetConfig);
                        }
                        if (metadata && metadata.contentType) {
                            // If the asset was served using HTTP, we shouldn't try to second guess by sniffing.
                            foundType(assets.lookupContentType(metadata.contentType));
                        } else {
                            // Work the magic
                            var fileProcess = child_process.spawn('file', ['-b', '--mime-type', '-']),
                                fileOutput = '';
                            fileProcess.stdout.on('data', function (chunk) {
                                fileOutput += chunk;
                            }).on('end', function () {
                                foundType(assets.lookupContentType(fileOutput.match(/^([^\n]*)/)[1]));
                            });
                            fileProcess.stdin.write(src);
                            fileProcess.stdin.end();
                        }
                    });
                }
            }
        }
    }
    cb(null, assetConfig);
};

module.exports = AssetConfigResolver;
<|endoftext|>


<commit_before>(function() {
    extend = function ( t, s, b ) {
        if (s) {
            for ( var k in s ) {
                if (!b || !t.hasOwnProperty(k)) {
                    t[k] = s[k];
                }
            }
        }
        return t;
    };

    var randomArray = function(array,source){
        if(array.length == 0) {
            return null;
        }
        var key =  parseInt(Math.random()*array.length);
        var res = array[key];
        if(source) {
            if(!source[res]) {
                var cloneArr = array.concat([]);
                cloneArr.splice(key,1);
                return randomArray(cloneArr,source);
            } else {
                return res;
            }
        } else {
            return res;
        }
    }
    var Snake = function(cfg){
        var _default = {
            columns : 25,
            rows : 25,
            unitLength : 15,
            containerId : '',
            defCss : 'snake',
            activeCssList : ['a','b','c'],
            allowBack : false,
            speed : 400,
            score : 1, //每吃一个食物所加的分数,
            range : 3, //出现特殊食物的机率
            maxUsers : 5
        };

        this.config = function(cfg){
            if(cfg) {
                extend(_default,cfg);
            }
            return  _default;
        }
    }

    Snake.prototype = {
        __fill : {}, //记录所有块。

        __map : {}, //此处记录块有没有被占用

        __keyMap : [],

        __foodPlugins : [],

        __timer  : null,

        __foodNums : 0,

        __events : {},

        players : {},

        playerIds : [],

        alives : 0,

        setKey :  function(l,t){
            return l + '_' + t;
        },
        draw : function(){
            var cfg = this.config();
            var container = document.getElementById(cfg.containerId);

            if(!container) {
                return;
            }

            for(var j = 1; j <= cfg.rows; j ++) {
                for(var i = 1; i <= cfg.columns ; i++) {
                    var key = this.setKey(i,j);
                    var span = document.createElement('span');
                    span.className = cfg.defCss;
                    span.style.display = 'inline-block';
                    span.style.width = cfg.unitLength + 'px';
                    span.style.height = cfg.unitLength + 'px';

                    this.__fill[key] = span;
                    this.__fill[key]._offset = {left : i, top :j};
                    this.__map[key] = 1;
                    this.__keyMap.push(key);
                    container.appendChild(span);
                }
            }
            container.style.width = cfg.unitLength * cfg.columns + 'px'
            container.style.height = cfg.unitLength * cfg.rows + 'px'
        },

        createBlock : function(l,t,c){
            var cfg = this.config();
            var key = this.setKey(l,t);
            if(!this.__fill[key] || (!this.__fill[key].plugin && this.__map[key] == 0)) {
                return null;
            }
            this.__fill[key].className = c || '';
            this.__map[key] = 0;
            return this.__fill[key];
        },

        deleteBlock : function(l,t) {
            var cfg = this.config();
            var key = this.setKey(l,t);
            if(!this.__fill[key]) {
                return;
            }
            this.__fill[key].className = cfg.defCss;
            this.__fill[key].plugin = null;
            this.__map[key] = 1;
        },

        randomBlock : function(c){
            var key = randomArray(this.__keyMap,this.__map);
            if(key) {
                var _key = key.split('_');
                return this.createBlock(_key[0],_key[1],c);
            }
            return null
        },

        regFood : function(o){
            this.__foodPlugins.push(o);
        },

        regBaseFood : function(json){
            var cfg = this.config();
            var _json = extend({
                fp : 0,
                effect : function(player,snake,food){
                    snake.body.unshift(food);
                },
                score : cfg.score,
                cssName : 'b'
            },json || {});
            this.__foodPlugins.unshift(_json);
        },

        createFood : function(c){
            var cfg = this.config();
            var range = Math.ceil(Math.random()*10)
            var plugin;
            if(range <= cfg.range && this.__foodPlugins.length >1) {
                var _food = this.__foodPlugins.concat([]);
                _food.shift();
                plugin = randomArray(_food);
            } else {
                plugin = this.__foodPlugins[0];
            }
            var fBody = this.randomBlock(plugin.cssName);
            fBody.plugin = plugin;
            this.__foodNums ++;
            return fBody;
        },
        removeFood : function(food){
            this.deleteBlock(food);
            this.__foodNums --;
            food.plugin = null;
            if(this.__foodNums <0) {
                this.__foodNums = 0;
            }
        },
        eatFood : function(player,snake,food){

            var cfg = this.config();
            food.plugin.effect.apply(this,arguments);
            player.scores += player.baseScore * food.plugin.score;
            this.evtFire('eat',arguments);
            this.removeFood(food);
            this.createFood();
        },
        createSnake : function(length, direction, id, c){
            var snakeBody = [];
            var cfg = this.config();
            switch(direction) {
                case 'up' :
                    while(length --) {
                        var l = Math.max(parseInt(cfg.columns/cfg.maxUsers),1) * id;
                        var t = cfg.rows - length;
                        snakeBody.push(this.createBlock(l,t,c));
                    }
                break;

                case 'down' :
                    while(length --) {
                        var l = Math.max(parseInt(cfg.columns/cfg.maxUsers),1) * id;
                        var t = length;
                        snakeBody.push(this.createBlock(l,t ,c));
                    }
                break;

                case 'left' :
                    while(length --) {
                        var l = cfg.columns - length;
                        var t = Math.max(parseInt(cfg.rows/cfg.maxUsers),1) * id;
                        snakeBody.push(this.createBlock(l,t,c));
                    }
                break;

                case 'right' :
                    while(length --) {
                        var l = cfg.columns + length;
                        var t = Math.max(parseInt(cfg.rows/cfg.maxUsers),1) * id;
                        snakeBody.push(this.createBlock(l, t ,c));
                    }
                break;
            }
            return snakeBody;
        },

        addPlayer : function(player){

            var _player = {
                length : 2, //初始长度
                direction : 'left',//初始方向
                name : 'user' + +new Date, //玩家名称
                scores : 0, //初始分数
                cssName : 'defUser', //初始样式
                baseScore : 1,
            };
            var cfg = this.config();
            var item = extend(_player,player || {});
            if(this.playerIds.length >= cfg.maxUsers) {
                return;
            }
            if(!this.players[item.name]) {

                this.players[item.name] = {
                    snake : {
                        cssName : item.cssName,
                        body : this.createSnake(item.length,item.direction,this.alives + 1,item.cssName),
                        speed : cfg.speed,
                        status : 'alive',
                        direction : item.direction
                    },
                    name : item.name,
                    scores : item.scores,
                    baseScore : item.baseScore, //分数倍数
                };
                for(var i = 0; i< cfg.maxUsers; i++) {
                    if(!this.playerIds[i]) {
                        this.playerIds[i] = this.players[item.name];
                        this.players[item.name].id = i;
                        break;
                    }
                }
                this.alives ++;
                this.evtFire('addplayer',[this.players]);
            }
        },

        addPlayers : function(players){
            for(var p=0; p<players.length; p++){
                this.addPlayer(players[p])
            }

        },

        removePlayer : function(playerName){
            if(this.players[playerName]){
                this.removeSnake(this.players[playerName].snake.body);
                this.playerIds[this.players[playerName].id] = undefined;
                this.players[playerName] = null;
                delete this.players[playerName];
                this.alives --
            }
        },

        removeSnake : function(snakeBody){
            for(var i = 0; i<snakeBody.length; i++) {
                var item = snakeBody[i];
                this.deleteBlock(item._offset.left,item._offset.top);
            }
        },

        __fastInit : function(){ //测试用
            this.draw() //画布
            var cfg = this.config();
            this.regBaseFood();
            this.addPlayers({

            });//增加玩家
            this.createFood();
        },

        init : function(){
            this.draw();
            var cfg = this.config();
            this.regBaseFood();

            //this.createFood();
            var _t = this;
        },

        snakeMove : function(){
            var cfg = this.config();

            if(this.alives == 0) {
                this.evtFire('gameover');
                this.pause();
            }
            for(var i in this.players) {
                var player = this.players[i];
                if(!player) {
                    continue;
                }
                if(player.snake.status == 'alive') {
                    var snake = player.snake.body;
                    var nextHead;
                    if(player.snake._direction) {
                        player.snake.direction = player.snake._direction;
                        player.snake._direction = null;
                    }
                    switch(player.snake.direction) {
                        case 'up' :
                            nextHead = this.createBlock(snake[0]._offset.left,snake[0]._offset.top - 1, player.snake.cssName);
                        break;
                        case 'down' :
                            nextHead = this.createBlock(snake[0]._offset.left,snake[0]._offset.top + 1, player.snake.cssName);
                        break;
                        case 'left' :
                            nextHead = this.createBlock(snake[0]._offset.left - 1,snake[0]._offset.top, player.snake.cssName);
                        break;
                        case 'right' :
                            nextHead = this.createBlock(snake[0]._offset.left + 1,snake[0]._offset.top, player.snake.cssName);
                        break;
                    }

                    if(!nextHead) {
                        console.info('game over');
                        player.snake.status = 'died';
                        return ;
                    }

                    if(nextHead.plugin) { //吃食物
                        this.eatFood(player,player.snake,nextHead);
                    } else {

                        var disBlock = snake.pop()
                        this.deleteBlock( disBlock._offset.left,disBlock._offset.top);
                        snake.unshift(nextHead);
                    }
                } else if(player.snake.status == 'died') {
                    var _player = extend({},player);
                    this.removePlayers(player.name);
                    this.evtFire('died',[_player]);
                }
            }
        },

        //运动相关
        run : function(){
            var _t =this;
            var cfg = _t.config();
            var cFood =  [0,1,2,2,3,3][this.alives];
            for(var i = 0; i< cFood; i++) {
                this.createFood();
            }
            _t.evtFire('start');
            if(_t.__timer) {
                clearInterval(this.__timer);
            }
            _t.__timer = setInterval(function(){
                _t.snakeMove();
            _t.evtFire('starting');
            },cfg.speed);
        },
        pause : function () {
            clearInterval(this.__timer);
            this.__timer = null
            this.evtFire('pause');
        },
        setDirection : function(snake,direction) { //设置移动方向
            var cfg  = this.config();
            if(snake.status != 'alive') {
                return;
            }
            var oldD = snake.direction, newD = direction;
            var rule = {
                'up' : 1,
                'left' : 2,
                'down' : 3,
                'right' : 4
            };

            if(!rule[newD]) {
                return false;
            }
            if(!cfg.allowBack && Math.abs(rule[oldD] - rule[newD]) == 2) {//不能直接向后转弯
                return false
            }
            snake._direction = direction;
            return true;
        },

        bind : function(evt, alias, handler){
            if(!this.__events[evt]) {
                this.__events[evt] = {};
            }
            this.__events[evt][alias] = handler;
        },
        unbind : function(evt,alias){
            if(!this.__events[evt]) {
                return;
            }
            if(alias) {
                this.__events[evt][alias] = null;
            } else {
                this.__events[evt] = null;
            }
        },
        evtFire : function(evt,data){
            if(!this.__events[evt]) {
                return;
            }

            for(var alias in  this.__events[evt]) {
                var func = this.__events[evt][alias];
                if(typeof func == 'function') {
                    this.__events[evt][alias].apply(this,data);
                }
            }
        }
    }
    window.Snake = Snake;
} ());

<commit_msg>snake.js<commit_after>(function() {
    extend = function ( t, s, b ) {
        if (s) {
            for ( var k in s ) {
                if (!b || !t.hasOwnProperty(k)) {
                    t[k] = s[k];
                }
            }
        }
        return t;
    };

    var randomArray = function(array,source){
        if(array.length == 0) {
            return null;
        }
        var key =  parseInt(Math.random()*array.length);
        var res = array[key];
        if(source) {
            if(!source[res]) {
                var cloneArr = array.concat([]);
                cloneArr.splice(key,1);
                return randomArray(cloneArr,source);
            } else {
                return res;
            }
        } else {
            return res;
        }
    }
    var Snake = function(cfg){
        var _default = {
            columns : 25,
            rows : 25,
            unitLength : 15,
            containerId : '',
            defCss : 'snake',
            activeCssList : ['a','b','c'],
            allowBack : false,
            speed : 400,
            score : 1, //每吃一个食物所加的分数,
            range : 3, //出现特殊食物的机率
            maxUsers : 5
        };

        this.config = function(cfg){
            if(cfg) {
                extend(_default,cfg);
            }
            return  _default;
        }
    }

    Snake.prototype = {
        __fill : {}, //记录所有块。

        __map : {}, //此处记录块有没有被占用

        __keyMap : [],

        __foodPlugins : [],

        __timer  : null,

        __foodNums : 0,

        __events : {},

        players : {},

        playerIds : [],

        alives : 0,

        setKey :  function(l,t){
            return l + '_' + t;
        },
        draw : function(){
            var cfg = this.config();
            var container = document.getElementById(cfg.containerId);

            if(!container) {
                return;
            }

            for(var j = 1; j <= cfg.rows; j ++) {
                for(var i = 1; i <= cfg.columns ; i++) {
                    var key = this.setKey(i,j);
                    var span = document.createElement('span');
                    span.className = cfg.defCss;
                    span.style.display = 'inline-block';
                    span.style.width = cfg.unitLength + 'px';
                    span.style.height = cfg.unitLength + 'px';

                    this.__fill[key] = span;
                    this.__fill[key]._offset = {left : i, top :j};
                    this.__map[key] = 1;
                    this.__keyMap.push(key);
                    container.appendChild(span);
                }
            }
            container.style.width = cfg.unitLength * cfg.columns + 'px'
            container.style.height = cfg.unitLength * cfg.rows + 'px'
        },

        createBlock : function(l,t,c){
            var cfg = this.config();
            var key = this.setKey(l,t);
            if(!this.__fill[key] || (!this.__fill[key].plugin && this.__map[key] == 0)) {
                return null;
            }
            this.__fill[key].className = c || '';
            this.__map[key] = 0;
            return this.__fill[key];
        },

        deleteBlock : function(l,t) {
            var cfg = this.config();
            var key = this.setKey(l,t);
            if(!this.__fill[key]) {
                return;
            }
            this.__fill[key].className = cfg.defCss;
            this.__fill[key].plugin = null;
            this.__map[key] = 1;
        },

        randomBlock : function(c){
            var key = randomArray(this.__keyMap,this.__map);
            if(key) {
                var _key = key.split('_');
                return this.createBlock(_key[0],_key[1],c);
            }
            return null
        },

        regFood : function(o){
            this.__foodPlugins.push(o);
        },

        regBaseFood : function(json){
            var cfg = this.config();
            var _json = extend({
                fp : 0,
                effect : function(player,snake,food){
                    snake.body.unshift(food);
                },
                score : cfg.score,
                cssName : 'b'
            },json || {});
            this.__foodPlugins.unshift(_json);
        },

        createFood : function(c){
            var cfg = this.config();
            var range = Math.ceil(Math.random()*10)
            var plugin;
            if(range <= cfg.range && this.__foodPlugins.length >1) {
                var _food = this.__foodPlugins.concat([]);
                _food.shift();
                plugin = randomArray(_food);
            } else {
                plugin = this.__foodPlugins[0];
            }
            var fBody = this.randomBlock(plugin.cssName);
            fBody.plugin = plugin;
            this.__foodNums ++;
            return fBody;
        },
        removeFood : function(food){
            this.deleteBlock(food);
            this.__foodNums --;
            food.plugin = null;
            if(this.__foodNums <0) {
                this.__foodNums = 0;
            }
        },
        eatFood : function(player,snake,food){

            var cfg = this.config();
            food.plugin.effect.apply(this,arguments);
            player.scores += player.baseScore * food.plugin.score;
            this.evtFire('eat',arguments);
            this.removeFood(food);
            this.createFood();
        },
        createSnake : function(length, direction, id, c){
            var snakeBody = [];
            var cfg = this.config();
            switch(direction) {
                case 'up' :
                    while(length --) {
                        var l = Math.max(parseInt(cfg.columns/cfg.maxUsers),1) * id;
                        var t = cfg.rows - length;
                        snakeBody.push(this.createBlock(l,t,c));
                    }
                break;

                case 'down' :
                    while(length --) {
                        var l = Math.max(parseInt(cfg.columns/cfg.maxUsers),1) * id;
                        var t = length;
                        snakeBody.push(this.createBlock(l,t ,c));
                    }
                break;

                case 'left' :
                    while(length --) {
                        var l = cfg.columns - length;
                        var t = Math.max(parseInt(cfg.rows/cfg.maxUsers),1) * id;
                        snakeBody.push(this.createBlock(l,t,c));
                    }
                break;

                case 'right' :
                    while(length --) {
                        var l = cfg.columns + length;
                        var t = Math.max(parseInt(cfg.rows/cfg.maxUsers),1) * id;
                        snakeBody.push(this.createBlock(l, t ,c));
                    }
                break;
            }
            return snakeBody;
        },

        addPlayer : function(player){

            var _player = {
                length : 2, //初始长度
                direction : 'left',//初始方向
                name : 'user' + +new Date, //玩家名称
                scores : 0, //初始分数
                cssName : 'defUser', //初始样式
                baseScore : 1,
            };
            var cfg = this.config();
            var item = extend(_player,player || {});
            if(this.playerIds.length >= cfg.maxUsers) {
                return;
            }
            if(!this.players[item.name]) {
                this.players[item.name] = {
                    snake : {
                        cssName : item.cssName,
                        body : this.createSnake(item.length,item.direction,this.alives + 1,item.cssName),
                        speed : cfg.speed,
                        status : 'alive',
                        direction : item.direction
                    },
                    name : item.name,
                    scores : item.scores,
                    baseScore : item.baseScore, //分数倍数
                };
                for(var i = 0; i< cfg.maxUsers; i++) {
                    if(!this.playerIds[i]) {
                        this.playerIds[i] = this.players[item.name];
                        this.players[item.name].id = i + 1;
                        break;
                    }
                }
                this.alives ++;
                this.evtFire('addplayer',[this.players]);
            }
        },

        addPlayers : function(players){
            for(var p=0; p<players.length; p++){
                this.addPlayer(players[p])
            }

        },

        removePlayer : function(playerName){
            if(this.players[playerName]){
                this.removeSnake(this.players[playerName].snake.body);
                this.playerIds[this.players[playerName].id - 1] = undefined;
                this.players[playerName] = null;
                delete this.players[playerName];
                this.alives --
            }
        },

        removeSnake : function(snakeBody){
            for(var i = 0; i<snakeBody.length; i++) {
                var item = snakeBody[i];
                this.deleteBlock(item._offset.left,item._offset.top);
            }
        },

        __fastInit : function(){ //测试用
            this.draw() //画布
            var cfg = this.config();
            this.regBaseFood();
            this.addPlayers({

            });//增加玩家
            this.createFood();
        },

        init : function(){
            this.draw();
            var cfg = this.config();
            this.regBaseFood();

            //this.createFood();
            var _t = this;
        },

        snakeMove : function(){
            var cfg = this.config();

            if(this.alives == 0) {
                this.evtFire('gameover');
                this.pause();
            }
            for(var i in this.players) {
                var player = this.players[i];
                if(!player) {
                    continue;
                }
                if(player.snake.status == 'alive') {
                    var snake = player.snake.body;
                    var nextHead;
                    if(player.snake._direction) {
                        player.snake.direction = player.snake._direction;
                        player.snake._direction = null;
                    }
                    switch(player.snake.direction) {
                        case 'up' :
                            nextHead = this.createBlock(snake[0]._offset.left,snake[0]._offset.top - 1, player.snake.cssName);
                        break;
                        case 'down' :
                            nextHead = this.createBlock(snake[0]._offset.left,snake[0]._offset.top + 1, player.snake.cssName);
                        break;
                        case 'left' :
                            nextHead = this.createBlock(snake[0]._offset.left - 1,snake[0]._offset.top, player.snake.cssName);
                        break;
                        case 'right' :
                            nextHead = this.createBlock(snake[0]._offset.left + 1,snake[0]._offset.top, player.snake.cssName);
                        break;
                    }

                    if(!nextHead) {
                        console.info('game over');
                        player.snake.status = 'died';
                        return ;
                    }

                    if(nextHead.plugin) { //吃食物
                        this.eatFood(player,player.snake,nextHead);
                    } else {

                        var disBlock = snake.pop()
                        this.deleteBlock( disBlock._offset.left,disBlock._offset.top);
                        snake.unshift(nextHead);
                    }
                } else if(player.snake.status == 'died') {
                    var _player = extend({},player);
                    this.removePlayer(player.name);
                    this.evtFire('died',[_player]);
                }
            }
        },

        //运动相关
        run : function(){
            var _t =this;
            var cfg = _t.config();
            var cFood =  [0,1,2,2,3,3][this.alives];
            for(var i = 0; i< cFood; i++) {
                this.createFood();
            }
            _t.evtFire('start');
            if(_t.__timer) {
                clearInterval(this.__timer);
            }
            _t.__timer = setInterval(function(){
                _t.snakeMove();
            _t.evtFire('starting');
            },cfg.speed);
        },
        pause : function () {
            clearInterval(this.__timer);
            this.__timer = null
            this.evtFire('pause');
        },
        setDirection : function(snake,direction) { //设置移动方向
            var cfg  = this.config();
            if(snake.status != 'alive') {
                return;
            }
            var oldD = snake.direction, newD = direction;
            var rule = {
                'up' : 1,
                'left' : 2,
                'down' : 3,
                'right' : 4
            };

            if(!rule[newD]) {
                return false;
            }
            if(!cfg.allowBack && Math.abs(rule[oldD] - rule[newD]) == 2) {//不能直接向后转弯
                return false
            }
            snake._direction = direction;
            return true;
        },

        bind : function(evt, alias, handler){
            if(!this.__events[evt]) {
                this.__events[evt] = {};
            }
            this.__events[evt][alias] = handler;
        },
        unbind : function(evt,alias){
            if(!this.__events[evt]) {
                return;
            }
            if(alias) {
                this.__events[evt][alias] = null;
            } else {
                this.__events[evt] = null;
            }
        },
        evtFire : function(evt,data){
            if(!this.__events[evt]) {
                return;
            }

            for(var alias in  this.__events[evt]) {
                var func = this.__events[evt][alias];
                if(typeof func == 'function') {
                    this.__events[evt][alias].apply(this,data);
                }
            }
        }
    }
    window.Snake = Snake;
} ());

<|endoftext|>


<commit_before>Array.prototype.setSlotsIfAbsent(
{
	init: function()
	{
		var args = [0, this.length];
		args.concatInPlace(this.slice());
		this.splice.apply(this, args);
	},

	empty: function()
	{
		this.splice(0, this.length);
		return this;
	},

	isEmpty: function()
	{
		return this.length == 0;
	},

	concatInPlace: function(anArray)
	{
		this.push.apply(this, anArray);
	},

	at: function(index)
	{
		if(index > 0)
		{
			return this[index];
		}
		else
		{
			return this[this.length + index];
		}
	},

	removeElements: function(elements)
	{
		elements.forEach(function(e){ this.remove(e) }, this);
		return this;
	},

	append: function(e)
	{
		this.push(e);
		return this;
	},

	prepend: function(e)
	{
		this.unshift(e);
		return this;
	},

	remove: function(e)
	{
		var i = this.indexOf(e);
		if(i > -1)
		{
			this.removeAt(i);
		}
		return this;
	},

	removeAt: function(i)
	{
		var v = this[i]
		this.splice(i, 1);
		return v;
	},

	copy: function()
	{
		return this.slice();
	},

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

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

	pushIfAbsent: function()
	{
		console.log("pushIfAbsent is deprecated.  Use appendIfAbsent instead.");
		return this.appendIfAbsent.apply(this, arguments);
	},

	appendAll: function(items)
	{
		this.splice(this.length, items.length, items);
		return this;
	},

	appendIfAbsent: function()
	{
		var self = this;
		this.argsAsArray(arguments).forEach(function(value)
		{
			if(self.indexOf(value) == -1)
			{
				self.push(value);
			}
		})

		return this;
	},

	split: function(subArrayCount)
	{
		var subArrays = [];

		var subArraySize = Math.ceil(this.length / subArrayCount);
		for(var i = 0; i < this.length; i += subArraySize)
		{
			var subArray = this.slice(i, i + subArraySize);
			if(subArray.length < subArraySize)
			{
				var lastSubArray = subArrays.pop();
				if(lastSubArray)
				{
					subArray = lastSubArray.concat(subArray);
				}
			}
			subArrays.push(subArray);
		}

		return subArrays;
	},

	map: function(fun /*, thisp*/)
	{
		var len = this.length;
		if(typeof fun != "function")
			throw new TypeError();

		var res = new Array(len);
		var thisp = arguments[1];
		for(var i = 0; i < len; i++)
		{
			if (i in this)
				res[i] = fun.call(thisp, this[i], i, this);
		}

		return res;
	},

	shuffle: function()
	{
		var i = this.length;
		if(i == 0) return false;
		while (-- i)
		{
			var j = Math.floor(Math.random() * ( i + 1 ));
			var tempi = this[i];
			var tempj = this[j];
			this[i] = tempj;
			this[j] = tempi;
		}
	},

	forEach: function(fun /*, thisp*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var thisp = arguments[1];
		for (var i = 0; i < len; i++)
		{
			if (i in this)
				fun.call(thisp, this[i], i, this);
		}
	},

	forEachCall: function(functionName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		args.push(0);
		this.forEach(function(e, i)
		{
			args[args.length - 1] = i;
			e[functionName].apply(e, args);
		});
		return this;
	},

	forEachPerform: function()
	{
		return this.forEachCall.apply(this, arguments);
	},

	sortByCalling: function(functionName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		return this.sort(function(x, y)
		{
			var xRes = x[functionName].apply(x, args);
			var yRes = y[functionName].apply(y, args);
			if(xRes < yRes)
			{
				return -1;
			}
			else if(yRes < xRes)
			{
				return 1;
			}
			else
			{
				return 0;
			}
		});
	},

	mapPerform: function(messageName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		args.push(0);
		return this.map(function(e, i)
		{
			args[args.length - 1] = i;
			return e[messageName].apply(e, args);
		});
	},

	detectByCalling: function()
	{
		console.log("detectByCalling is deprecated.  Use detectByPerforming instead.");
		return this.detectByPerforming.apply(this, arguments);
	},

	detectByPerforming: function(functionName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		return this.detect(function(e, i)
		{
			return e[functionName].apply(e, args);
		});
	},

	reduce: function(fun /*, initial*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		// no value to return if no initial value and an empty array
		if (len == 0 && arguments.length == 1)
			throw new TypeError();

		var i = 0;
		if (arguments.length >= 2)
		{
			var rv = arguments[1];
		}
		else
		{
			do
			{
				if (i in this)
				{
					rv = this[i++];
					break;
				}

				// if array contains no values, no initial value to return
				if (++i >= len)
					throw new TypeError();
				}
			while (true);
		}

		for (; i < len; i++)
		{
			if (i in this)
				rv = fun.call(null, rv, this[i], i, this);
		}

		return rv;
	},

	filter: function(fun /*, thisp*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var res = new Array();
		var thisp = arguments[1];
		for (var i = 0; i < len; i++)
	    {
			if (i in this)
			{
				var val = this[i]; // in case fun mutates this
				if (fun.call(thisp, val, i, this))
					res.push(val);
			}
		}

		return res;
	},

	filterByPerforming: function(messageName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		args.push(0);
		return this.filter(function(e, i)
		{
			args[args.length - 1] = i;
			return e[messageName].apply(e, args);
		});
	},

	select: function()
	{
		return this.filter.apply(this, arguments);
	},

	detect: function(callback)
	{
		for(var i = 0; i < this.length; i++)
		{
			if(callback(this[i]))
			{
				return this[i];
			}
		}

		return null;
	},

	detectIndex: function(callback)
	{
		for(var i = 0; i < this.length; i++)
		{
			if(callback(this[i]))
			{
				return i;
			}
		}

		return null;
	},

	max: function(callback)
	{
		var m = undefined;
		var mObject = undefined;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			if(m == undefined || v > m)
			{
				m = v;
				mObject = this[i];
			}
		}

		return mObject;
	},

	maxIndex: function(callback)
	{
		var m = undefined;
		var index = 0;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			if(m == undefined || v > m)
			{
				m = v;
				index = i;
			}
		}

		return index;
	},

	min: function(callback)
	{
		var m = undefined;
		var mObject = undefined;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			if(m == undefined || v < m)
			{
				m = v;
				mObject = this[i];
			}
		}

		return mObject;
	},

	minIndex: function(callback)
	{
		var m = undefined;
		var index = 0;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			if(m == undefined || v < m)
			{
				m = v;
				index = i;
			}
		}

		return index;
	},

	sum: function(callback)
	{
		var m = undefined;
		var sum = 0;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			sum = sum + v;
		}

		return sum;
	},

	some: function(fun /*, thisp*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var thisp = arguments[1];
		for (var i = 0; i < len; i++)
		{
			if (i in this && fun.call(thisp, this[i], i, this))
				return true;
		}

		return false;
	},

	every: function(fun /*, thisp*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var thisp = arguments[1];
		for (var i = 0; i < len; i++)
		{
			if (i in this && !fun.call(thisp, this[i], i, this))
				return false;
		}

		return true;
	},

	allRespondTrue: function(message)
	{
		return this.every(function(e){ return e.perform(message) });
	},

	firstRespondingTrue: function(message)
	{
		return this.detect(function(e){ return e.perform(message) });
	},

	indexOf: function(elt /*, from*/)
	{
		var len = this.length;

		var from = Number(arguments[1]) || 0;
		from = (from < 0)
			? Math.ceil(from)
			: Math.floor(from);
		if (from < 0)
			from += len;

		for (; from < len; from++)
		{
			if (from in this &&
				this[from] === elt)
			return from;
		}
		return -1;
	},

	contains: function(element)
	{
		return this.indexOf(element) > -1;
	},

	isIntersectedBy: function(anArray)
	{
		var length = this.length
		for(var i = 0; i < length; i ++)
		{
			if (anArray.contains(this[i]))
			{
				return true;
			}
		}

		return false;
	},

	removeFirst: function ()
	{
		return this.shift();
	},

	hasPrefix: function(otherArray)
	{
		if(this.length < otherArray.length) { return false; }

		for(var i = 0; i < this.length; i ++)
		{
			if(this[i] != otherArray[i]) return false;
		}

		return true;
	},

	toString: function()
	{
		var s = "[";

		for(var i = 0; i < this.length; i ++)
		{
			var value = this[i];

			if (i != 0) s = s + ","

			if(typeof(value) == "string")
			{
				s = s + "\"" + value + "\"";
			}
			else
			{
				s = s + value;
			}
		}

		return s + "]";
	},

	isEqual: function(otherArray)
	{
		if(this.length != otherArray.length) { return false; }

		for(var i = 0; i < this.length; i ++)
		{
			if(this[i] != otherArray[i]) return false;
		}

		return true;
	},

	elementWith: function(accessorFunctionName, value)
	{
		var e = this[this.mapPerform(accessorFunctionName).indexOf(value)];
		return e === undefined ? null : e;
	},

	atInsert: function(i, e)
	{
		this.splice(i, 0, e);
	},

	size: function()
	{
		return this.length;
	},

	isEqual: function(testArr)
	{
	    return this.compare(testArr);
	},

	compare: function(testArr)
	{
	    if (this.length != testArr.length)
		{
			return false;
	    }

		for (var i = 0; i < testArr.length; i++)
		{
			var a = this[i];
			var b = testArr[i];

			if (a == null || b == null)
			{
				if(a != b)
				{
					return false;
				}
			}
	        else if (a.compare)
			{
	            if (!a.compare(b))
				{
					return false;
	        	}
			}
	   		else if (a !== b)
			{
				return false;
	    	}
		}

	    return true;
	},

	flattened: function()
	{
		var out = [];
		for (var i = 0; i < this.length; i++)
		{
			var v = this[i];
			if(typeof(v) == "array")
			{
				out.appendAll(v);
			}
			else
			{
				out.push(v);
			}
		}

		return v;
	},

	complement: function(anotherArray)
	{
		var result = this.copy();

		anotherArray.forEach(function(e){
			result.remove(e);
		});

		return result;
	}
});<commit_msg>Added Array.asMap<commit_after>Array.prototype.setSlotsIfAbsent(
{
	init: function()
	{
		var args = [0, this.length];
		args.concatInPlace(this.slice());
		this.splice.apply(this, args);
	},

	empty: function()
	{
		this.splice(0, this.length);
		return this;
	},

	isEmpty: function()
	{
		return this.length == 0;
	},

	concatInPlace: function(anArray)
	{
		this.push.apply(this, anArray);
	},

	at: function(index)
	{
		if(index > 0)
		{
			return this[index];
		}
		else
		{
			return this[this.length + index];
		}
	},

	removeElements: function(elements)
	{
		elements.forEach(function(e){ this.remove(e) }, this);
		return this;
	},

	append: function(e)
	{
		this.push(e);
		return this;
	},

	prepend: function(e)
	{
		this.unshift(e);
		return this;
	},

	remove: function(e)
	{
		var i = this.indexOf(e);
		if(i > -1)
		{
			this.removeAt(i);
		}
		return this;
	},

	removeAt: function(i)
	{
		var v = this[i]
		this.splice(i, 1);
		return v;
	},

	copy: function()
	{
		return this.slice();
	},

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

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

	pushIfAbsent: function()
	{
		console.log("pushIfAbsent is deprecated.  Use appendIfAbsent instead.");
		return this.appendIfAbsent.apply(this, arguments);
	},

	appendAll: function(items)
	{
		this.splice(this.length, items.length, items);
		return this;
	},

	appendIfAbsent: function()
	{
		var self = this;
		this.argsAsArray(arguments).forEach(function(value)
		{
			if(self.indexOf(value) == -1)
			{
				self.push(value);
			}
		})

		return this;
	},

	split: function(subArrayCount)
	{
		var subArrays = [];

		var subArraySize = Math.ceil(this.length / subArrayCount);
		for(var i = 0; i < this.length; i += subArraySize)
		{
			var subArray = this.slice(i, i + subArraySize);
			if(subArray.length < subArraySize)
			{
				var lastSubArray = subArrays.pop();
				if(lastSubArray)
				{
					subArray = lastSubArray.concat(subArray);
				}
			}
			subArrays.push(subArray);
		}

		return subArrays;
	},

	map: function(fun /*, thisp*/)
	{
		var len = this.length;
		if(typeof fun != "function")
			throw new TypeError();

		var res = new Array(len);
		var thisp = arguments[1];
		for(var i = 0; i < len; i++)
		{
			if (i in this)
				res[i] = fun.call(thisp, this[i], i, this);
		}

		return res;
	},

	shuffle: function()
	{
		var i = this.length;
		if(i == 0) return false;
		while (-- i)
		{
			var j = Math.floor(Math.random() * ( i + 1 ));
			var tempi = this[i];
			var tempj = this[j];
			this[i] = tempj;
			this[j] = tempi;
		}
	},

	forEach: function(fun /*, thisp*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var thisp = arguments[1];
		for (var i = 0; i < len; i++)
		{
			if (i in this)
				fun.call(thisp, this[i], i, this);
		}
	},

	forEachCall: function(functionName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		args.push(0);
		this.forEach(function(e, i)
		{
			args[args.length - 1] = i;
			e[functionName].apply(e, args);
		});
		return this;
	},

	forEachPerform: function()
	{
		return this.forEachCall.apply(this, arguments);
	},

	sortByCalling: function(functionName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		return this.sort(function(x, y)
		{
			var xRes = x[functionName].apply(x, args);
			var yRes = y[functionName].apply(y, args);
			if(xRes < yRes)
			{
				return -1;
			}
			else if(yRes < xRes)
			{
				return 1;
			}
			else
			{
				return 0;
			}
		});
	},

	mapPerform: function(messageName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		args.push(0);
		return this.map(function(e, i)
		{
			args[args.length - 1] = i;
			return e[messageName].apply(e, args);
		});
	},

	detectByCalling: function()
	{
		console.log("detectByCalling is deprecated.  Use detectByPerforming instead.");
		return this.detectByPerforming.apply(this, arguments);
	},

	detectByPerforming: function(functionName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		return this.detect(function(e, i)
		{
			return e[functionName].apply(e, args);
		});
	},

	reduce: function(fun /*, initial*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		// no value to return if no initial value and an empty array
		if (len == 0 && arguments.length == 1)
			throw new TypeError();

		var i = 0;
		if (arguments.length >= 2)
		{
			var rv = arguments[1];
		}
		else
		{
			do
			{
				if (i in this)
				{
					rv = this[i++];
					break;
				}

				// if array contains no values, no initial value to return
				if (++i >= len)
					throw new TypeError();
				}
			while (true);
		}

		for (; i < len; i++)
		{
			if (i in this)
				rv = fun.call(null, rv, this[i], i, this);
		}

		return rv;
	},

	filter: function(fun /*, thisp*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var res = new Array();
		var thisp = arguments[1];
		for (var i = 0; i < len; i++)
	    {
			if (i in this)
			{
				var val = this[i]; // in case fun mutates this
				if (fun.call(thisp, val, i, this))
					res.push(val);
			}
		}

		return res;
	},

	filterByPerforming: function(messageName)
	{
		var args = this.argsAsArray(arguments).slice(1);
		args.push(0);
		return this.filter(function(e, i)
		{
			args[args.length - 1] = i;
			return e[messageName].apply(e, args);
		});
	},

	select: function()
	{
		return this.filter.apply(this, arguments);
	},

	detect: function(callback)
	{
		for(var i = 0; i < this.length; i++)
		{
			if(callback(this[i]))
			{
				return this[i];
			}
		}

		return null;
	},

	detectIndex: function(callback)
	{
		for(var i = 0; i < this.length; i++)
		{
			if(callback(this[i]))
			{
				return i;
			}
		}

		return null;
	},

	max: function(callback)
	{
		var m = undefined;
		var mObject = undefined;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			if(m == undefined || v > m)
			{
				m = v;
				mObject = this[i];
			}
		}

		return mObject;
	},

	maxIndex: function(callback)
	{
		var m = undefined;
		var index = 0;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			if(m == undefined || v > m)
			{
				m = v;
				index = i;
			}
		}

		return index;
	},

	min: function(callback)
	{
		var m = undefined;
		var mObject = undefined;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			if(m == undefined || v < m)
			{
				m = v;
				mObject = this[i];
			}
		}

		return mObject;
	},

	minIndex: function(callback)
	{
		var m = undefined;
		var index = 0;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			if(m == undefined || v < m)
			{
				m = v;
				index = i;
			}
		}

		return index;
	},

	sum: function(callback)
	{
		var m = undefined;
		var sum = 0;
		var length = this.length;

		for(var i = 0; i < length; i++)
		{
			var v = this[i];
			if(callback) v = callback(v);

			sum = sum + v;
		}

		return sum;
	},

	some: function(fun /*, thisp*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var thisp = arguments[1];
		for (var i = 0; i < len; i++)
		{
			if (i in this && fun.call(thisp, this[i], i, this))
				return true;
		}

		return false;
	},

	every: function(fun /*, thisp*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var thisp = arguments[1];
		for (var i = 0; i < len; i++)
		{
			if (i in this && !fun.call(thisp, this[i], i, this))
				return false;
		}

		return true;
	},

	allRespondTrue: function(message)
	{
		return this.every(function(e){ return e.perform(message) });
	},

	firstRespondingTrue: function(message)
	{
		return this.detect(function(e){ return e.perform(message) });
	},

	indexOf: function(elt /*, from*/)
	{
		var len = this.length;

		var from = Number(arguments[1]) || 0;
		from = (from < 0)
			? Math.ceil(from)
			: Math.floor(from);
		if (from < 0)
			from += len;

		for (; from < len; from++)
		{
			if (from in this &&
				this[from] === elt)
			return from;
		}
		return -1;
	},

	contains: function(element)
	{
		return this.indexOf(element) > -1;
	},

	isIntersectedBy: function(anArray)
	{
		var length = this.length
		for(var i = 0; i < length; i ++)
		{
			if (anArray.contains(this[i]))
			{
				return true;
			}
		}

		return false;
	},

	removeFirst: function ()
	{
		return this.shift();
	},

	hasPrefix: function(otherArray)
	{
		if(this.length < otherArray.length) { return false; }

		for(var i = 0; i < this.length; i ++)
		{
			if(this[i] != otherArray[i]) return false;
		}

		return true;
	},

	toString: function()
	{
		var s = "[";

		for(var i = 0; i < this.length; i ++)
		{
			var value = this[i];

			if (i != 0) s = s + ","

			if(typeof(value) == "string")
			{
				s = s + "\"" + value + "\"";
			}
			else
			{
				s = s + value;
			}
		}

		return s + "]";
	},

	isEqual: function(otherArray)
	{
		if(this.length != otherArray.length) { return false; }

		for(var i = 0; i < this.length; i ++)
		{
			if(this[i] != otherArray[i]) return false;
		}

		return true;
	},

	elementWith: function(accessorFunctionName, value)
	{
		var e = this[this.mapPerform(accessorFunctionName).indexOf(value)];
		return e === undefined ? null : e;
	},

	atInsert: function(i, e)
	{
		this.splice(i, 0, e);
	},

	size: function()
	{
		return this.length;
	},

	isEqual: function(testArr)
	{
	    return this.compare(testArr);
	},

	compare: function(testArr)
	{
	    if (this.length != testArr.length)
		{
			return false;
	    }

		for (var i = 0; i < testArr.length; i++)
		{
			var a = this[i];
			var b = testArr[i];

			if (a == null || b == null)
			{
				if(a != b)
				{
					return false;
				}
			}
	        else if (a.compare)
			{
	            if (!a.compare(b))
				{
					return false;
	        	}
			}
	   		else if (a !== b)
			{
				return false;
	    	}
		}

	    return true;
	},

	flattened: function()
	{
		var out = [];
		for (var i = 0; i < this.length; i++)
		{
			var v = this[i];
			if(typeof(v) == "array")
			{
				out.appendAll(v);
			}
			else
			{
				out.push(v);
			}
		}

		return v;
	},

	complement: function(anotherArray)
	{
		var result = this.copy();

		anotherArray.forEach(function(e){
			result.remove(e);
		});

		return result;
	},

	asMap: function()
	{
		var map = {};
		this.forEach(function(pair){
			map[pair[0]] = pair[1];
		});

		return map;
	}
});<|endoftext|>


<commit_before>var fs = require('fs'),
	path = require('path'),
	os = require('os'),
	wrench = require('wrench'),
	colors = require('colors'),
	TU = require('../lib/testUtils'),
	CONST = require('../../Alloy/common/constants'),
	_ = require('../../Alloy/lib/alloy/underscore')._,
	platforms = require('../../platforms/index'),
	sep = process.platform !== 'win32' ? '/' : '\\';

var TIMEOUT_COMPILE = process.platform !== 'win32' ? 10000 : 20000;
var TIMEOUT_PREP = process.platform !== 'win32' ? 10000 : 30000;
var GEN_FOLDER = '_generated';

var alloyRoot = path.join(__dirname,'..','..'),
	paths = {
		apps: path.join(alloyRoot,'test','apps'),
		harness: path.join(alloyRoot,'test','projects','Harness')
	},
	compilerDirectives = (function() {
		var cds = [];
		_.each(_.keys(platforms), function(p) {
			cds.push('OS_' + p.toUpperCase());
		});
		cds.concat(_.pluck(CONST.DEPLOY_TYPES,'key'));
		return cds;
	})(),
	cdRegex = new RegExp('(?:' + compilerDirectives.join('|') + ')');

// The alloy command test suite
describe('alloy compile', function() {
	TU.addMatchers();

	// Iterate through each test app and make sure it compiles for all platforms
	_.each(wrench.readdirSyncRecursive(paths.apps), function(file) {
		// are we testing only a specific app?
		if (process.env.app && file !== process.env.app) { return; }

		// TODO: Stop skipping the ui/navwindow test when TiSDK 3.1.3 is in the HarnessTemplate
		//       tiapp.xml. We skip it now because it purposely fails compilation on any SDK below
		//       TiSDK 3.1.3, where Ti.UI.iOS.NavigationWindow was introduced.
		if (file === 'ui'+sep+'navwindow' || file === 'testing'+sep+'ALOY-818' || file === 'testing'+sep+'ALOY-840') { return; }

		describe(file.yellow, function() {
			var indexJs = path.join(paths.apps,file,'controllers','index.js');
			if (!path.existsSync(indexJs) || indexJs.indexOf(GEN_FOLDER) !== -1) { return; }

			it('preparing test app', function() {
				TU.asyncExecTest('jake app:setup dir=' + file + ' quiet=1', { timeout: TIMEOUT_PREP });
			});

			_.each(platforms, function(platform,k) {
				if (process.platform === 'darwin' && platform.platform === 'blackberry') {
					return;
				}

				describe(('[' + platform.platform + ']').cyan, function () {
						it('compiles without critical error',
						function() {
							TU.asyncExecTest(
								'alloy compile ' + paths.harness + ' --config platform=' + platform.platform, {
								test: function() {
									// Make sure there were no compile errors
									if (file === 'testing'+sep+'ALOY-887') {
										// this test specifically tests a compiler error
										expect(this.output.error).toBeTruthy();
									} else {
										expect(this.output.error).toBeFalsy();
									}
								},
								timeout: TIMEOUT_COMPILE
							}
						);
					});

					it('leaves no compiler directives in generated code', function() {
						var hrDir = path.join(paths.harness,'Resources');
						var cPaths = [
							path.join(hrDir,'alloy'),
							path.join(hrDir,platform.titaniumFolder,'alloy')
						];

						_.each(cPaths, function(cPath) {
							if (file === 'testing'+sep+'ALOY-887') {
								// skip this test since this app forces a compile error
								return;
							}
							if (!fs.existsSync(cPath)) { return; }
							var files = wrench.readdirSyncRecursive(cPath);
							_.each(files, function(file) {
								var fullpath = path.join(cPath,file);
								if (!fs.statSync(fullpath).isFile() ||
									!/\.js$/.test(fullpath)) {
									return;
								}
								var content = fs.readFileSync(fullpath, 'utf8');
								expect(cdRegex.test(content)).toBeFalsy();
							});
						});
					});

					it('has no undefined style entries', function() {
						// skip this test, since it specifically tests undefined values in TSS
						if (file === 'testing'+sep+'ALOY-822') {
							return;
						}

						var hrDir = path.join(paths.harness,'Resources');
						var cPaths = [
							path.join(hrDir,'alloy','styles'),
							path.join(hrDir,platform.titaniumFolder,'alloy','styles')
						];

						_.each(cPaths, function(cPath) {
							if (!fs.existsSync(cPath)) { return; }
							var files = wrench.readdirSyncRecursive(cPath);
							_.each(files, function(file) {
								var fullpath = path.join(cPath,file);
								if (!fs.statSync(fullpath).isFile() ||
									!/\.js$/.test(fullpath)) {
									return;
								}

								// TODO: Can no longer require() the styles since they
								//       are preprocessed for runtime now. Find a better
								//       way than this lazy text check to verify that
								//       there's no undefined keys in the styles.
								expect(fs.readFileSync(fullpath,'utf8').indexOf('undefined')).toEqual(-1);
								// var json = require(fullpath);
								// expect(json).toHaveNoUndefinedStyles();
							});
						});
					});

					var genFolder = path.join(paths.apps,file,GEN_FOLDER,platform.platform);
					if (!fs.existsSync(genFolder)) { return; }
					var hrFolder = path.join(paths.harness, 'Resources', platform.titaniumFolder);
					var files = wrench.readdirSyncRecursive(genFolder);

					os.platform() === 'darwin' && _.each(files, function(gFile) {
						var goodFile = path.join(genFolder,gFile);
						if (!fs.statSync(goodFile).isFile()) { return; }
						var newFile = path.join(hrFolder,gFile);

						it ('generated a ' + gFile.yellow + ' file', function() {
							expect(fs.existsSync(newFile)).toBeTruthy();
						});

						it('matches known good generated code for ' + gFile.yellow, function () {
							var goodFileContents = fs.readFileSync(goodFile, 'utf8');
							var newFileContents = fs.readFileSync(newFile, 'utf8');

/*						if(goodFileContents !== newFileContents) {
							// Cheat way to re-generate known-good files
							// uncomment this block, run jake test:spec[compile.js]
							// then re-comment this block. jake test:all should now be happy
							console.log('>>>> writing a new goodFile');
							fs.createReadStream(newFile).pipe(fs.createWriteStream(goodFile));
							goodFileContents = fs.readFileSync(goodFile, 'utf8');
						}
*/
							expect(goodFileContents === newFileContents).toBeTruthy();
						});
					});
				});
			});
		});
	});
});
<commit_msg>[ALOY-932] update compile.js to exclude this ticket's test app<commit_after>var fs = require('fs'),
	path = require('path'),
	os = require('os'),
	wrench = require('wrench'),
	colors = require('colors'),
	TU = require('../lib/testUtils'),
	CONST = require('../../Alloy/common/constants'),
	_ = require('../../Alloy/lib/alloy/underscore')._,
	platforms = require('../../platforms/index'),
	sep = process.platform !== 'win32' ? '/' : '\\';

var TIMEOUT_COMPILE = process.platform !== 'win32' ? 10000 : 20000;
var TIMEOUT_PREP = process.platform !== 'win32' ? 10000 : 30000;
var GEN_FOLDER = '_generated';
var TEST_FOLDER = 'testing';
var EXCLUDE_FOLDERS = [
	'ui'+sep+'navwindow',
	TEST_FOLDER+sep+'ALOY-818',
	TEST_FOLDER+sep+'ALOY-840',
	TEST_FOLDER+sep+'ALOY-1080',
	TEST_FOLDER+sep+'ALOY-932'
];

var alloyRoot = path.join(__dirname,'..','..'),
	paths = {
		apps: path.join(alloyRoot,'test','apps'),
		harness: path.join(alloyRoot,'test','projects','Harness')
	},
	compilerDirectives = (function() {
		var cds = [];
		_.each(_.keys(platforms), function(p) {
			cds.push('OS_' + p.toUpperCase());
		});
		cds.concat(_.pluck(CONST.DEPLOY_TYPES,'key'));
		return cds;
	})(),
	cdRegex = new RegExp('(?:' + compilerDirectives.join('|') + ')');

// The alloy command test suite
describe('alloy compile', function() {
	TU.addMatchers();

	// Iterate through each test app and make sure it compiles for all platforms
	_.each(wrench.readdirSyncRecursive(paths.apps), function(file) {
		// are we testing only a specific app?
		if (process.env.app && file !== process.env.app) { return; }

		// TODO: Stop skipping the ui/navwindow test when TiSDK 3.1.3 is in the HarnessTemplate
		//       tiapp.xml. We skip it now because it purposely fails compilation on any SDK below
		//       TiSDK 3.1.3, where Ti.UI.iOS.NavigationWindow was introduced.
		if (_.contains(EXCLUDE_FOLDERS, file)) { return; }

		describe(file.yellow, function() {
			var indexJs = path.join(paths.apps,file,'controllers','index.js');
			if (!path.existsSync(indexJs) || indexJs.indexOf(GEN_FOLDER) !== -1) { return; }

			it('preparing test app', function() {
				TU.asyncExecTest('jake app:setup dir=' + file + ' quiet=1', { timeout: TIMEOUT_PREP });
			});

			_.each(platforms, function(platform,k) {
				if (process.platform === 'darwin' && platform.platform === 'blackberry') {
					return;
				}

				describe(('[' + platform.platform + ']').cyan, function () {
						it('compiles without critical error',
						function() {
							TU.asyncExecTest(
								'alloy compile ' + paths.harness + ' --config platform=' + platform.platform, {
								test: function() {
									// Make sure there were no compile errors
									if (file === 'testing'+sep+'ALOY-887') {
										// this test specifically tests a compiler error
										expect(this.output.error).toBeTruthy();
									} else {
										expect(this.output.error).toBeFalsy();
									}
								},
								timeout: TIMEOUT_COMPILE
							}
						);
					});

					it('leaves no compiler directives in generated code', function() {
						var hrDir = path.join(paths.harness,'Resources');
						var cPaths = [
							path.join(hrDir,'alloy'),
							path.join(hrDir,platform.titaniumFolder,'alloy')
						];

						_.each(cPaths, function(cPath) {
							if (file === 'testing'+sep+'ALOY-887') {
								// skip this test since this app forces a compile error
								return;
							}
							if (!fs.existsSync(cPath)) { return; }
							var files = wrench.readdirSyncRecursive(cPath);
							_.each(files, function(file) {
								var fullpath = path.join(cPath,file);
								if (!fs.statSync(fullpath).isFile() ||
									!/\.js$/.test(fullpath)) {
									return;
								}
								var content = fs.readFileSync(fullpath, 'utf8');
								expect(cdRegex.test(content)).toBeFalsy();
							});
						});
					});

					it('has no undefined style entries', function() {
						// skip this test, since it specifically tests undefined values in TSS
						if (file === 'testing'+sep+'ALOY-822') {
							return;
						}

						var hrDir = path.join(paths.harness,'Resources');
						var cPaths = [
							path.join(hrDir,'alloy','styles'),
							path.join(hrDir,platform.titaniumFolder,'alloy','styles')
						];

						_.each(cPaths, function(cPath) {
							if (!fs.existsSync(cPath)) { return; }
							var files = wrench.readdirSyncRecursive(cPath);
							_.each(files, function(file) {
								var fullpath = path.join(cPath,file);
								if (!fs.statSync(fullpath).isFile() ||
									!/\.js$/.test(fullpath)) {
									return;
								}

								// TODO: Can no longer require() the styles since they
								//       are preprocessed for runtime now. Find a better
								//       way than this lazy text check to verify that
								//       there's no undefined keys in the styles.
								expect(fs.readFileSync(fullpath,'utf8').indexOf('undefined')).toEqual(-1);
								// var json = require(fullpath);
								// expect(json).toHaveNoUndefinedStyles();
							});
						});
					});

					var genFolder = path.join(paths.apps,file,GEN_FOLDER,platform.platform);
					if (!fs.existsSync(genFolder)) { return; }
					var hrFolder = path.join(paths.harness, 'Resources', platform.titaniumFolder);
					var files = wrench.readdirSyncRecursive(genFolder);

					os.platform() === 'darwin' && _.each(files, function(gFile) {
						var goodFile = path.join(genFolder,gFile);
						if (!fs.statSync(goodFile).isFile()) { return; }
						var newFile = path.join(hrFolder,gFile);

						it ('generated a ' + gFile.yellow + ' file', function() {
							expect(fs.existsSync(newFile)).toBeTruthy();
						});

						it('matches known good generated code for ' + gFile.yellow, function () {
							var goodFileContents = fs.readFileSync(goodFile, 'utf8');
							var newFileContents = fs.readFileSync(newFile, 'utf8');

/*						if(goodFileContents !== newFileContents) {
							// Cheat way to re-generate known-good files
							// uncomment this block, run jake test:spec[compile.js]
							// then re-comment this block. jake test:all should now be happy
							console.log('>>>> writing a new goodFile');
							fs.createReadStream(newFile).pipe(fs.createWriteStream(goodFile));
							goodFileContents = fs.readFileSync(goodFile, 'utf8');
						}
*/
							expect(goodFileContents === newFileContents).toBeTruthy();
						});
					});
				});
			});
		});
	});
});
<|endoftext|>


<commit_before>var drawWords = function (jsonResponse) {

    document.getElementById("wordsDiv").innerHTML = "";
    var emojis = JSON.parse('{"person": "👤", "man": "👨","woman":"👩","anger": "😡","contempt": "😒","disgust": "😷","fear": "😨","happiness": "😃","neutral": "😐","sadness": "😔","surprise": "😨","indoor": "🏠","looking": "👀","staring": "👀","glasses":"👓" }');

    var jsonMessage=JSON.parse(jsonResponse);
   var tags = jsonMessage.ComputerVision.tags;
  console.log(tags.length);
  console.warn(tags);
   var newWord = document.createElement("span");
   var emojisDisplay= "Faces Found: " +jsonMessage.ComputerVision.faces.length+"  ";
  for (var i = 0; i < tags.length; i++) {

    if(tags[i].confidence>.8){
      if(emojis[tags[i].name]== null){
            emojisDisplay+= tags[i].name +"  ";
       }else{
         emojisDisplay+= emojis[tags[i].name] +"  ";
       }
    }

  }

  for(var i = 0; i < jsonMessage.Emotion.length; i++){
    var emotionFound=jsonMessage.Emotion[i];
    var emotionProb="default";
      for(var key in Object.keys(emotionFound.scores)){
          if (typeof(emotionFound.scores[emotionProb]) == "undefined" ||  emotionFound.scores[Object.keys(emotionFound.scores)[key]]>emotionFound.scores[emotionProb]){
            emotionProb=Object.keys(emotionFound.scores)[key];
          }
      }
       emojisDisplay+= emojis[emotionProb] +"  ";
  }

    newWord.textContent=emojisDisplay;

  document.getElementById("wordsDiv").appendChild(newWord);

}

<commit_msg>validate message format<commit_after>var drawWords = function (jsonResponse) {

    document.getElementById("wordsDiv").innerHTML = "";
    var emojis = JSON.parse('{"person": "👤", "man": "👨","woman":"👩","anger": "😡","contempt": "😒","disgust": "😷","fear": "😨","happiness": "😃","neutral": "😐","sadness": "😔","surprise": "😨","indoor": "🏠","looking": "👀","staring": "👀","glasses":"👓" }');

    var jsonMessage=JSON.parse(jsonResponse);
   var tags = jsonMessage.ComputerVision.tags;
   if (tags === undefined || tags === null) {
   console.log('not valid response for tags ')
   }else{
    console.log(tags.length);
    console.warn(tags);
     var newWord = document.createElement("span");
     var emojisDisplay= "Faces Found: " +jsonMessage.ComputerVision.faces.length+"  ";
      for (var i = 0; i < tags.length; i++) {

        if(tags[i].confidence>.8){
          if(emojis[tags[i].name]== null){
                emojisDisplay+= tags[i].name +"  ";
           }else{
             emojisDisplay+= emojis[tags[i].name] +"  ";
           }
        }

      }

   }

   if (jsonMessage.Emotion.length === undefined || jsonMessage.Emotion.length === null) {
   console.log('not valid response for Emotions ')
   }else{
        for(var i = 0; i < jsonMessage.Emotion.length; i++){
        var emotionFound=jsonMessage.Emotion[i];
        var emotionProb="default";
          for(var key in Object.keys(emotionFound.scores)){
              if (typeof(emotionFound.scores[emotionProb]) == "undefined" ||  emotionFound.scores[Object.keys(emotionFound.scores)[key]]>emotionFound.scores[emotionProb]){
                emotionProb=Object.keys(emotionFound.scores)[key];
              }
          }
           emojisDisplay+= emojis[emotionProb] +"  ";
      }
   }

    newWord.textContent=emojisDisplay;

  document.getElementById("wordsDiv").appendChild(newWord);

}

<|endoftext|>