<commit_before>/* module make possible connectoin thru socket.io on a server */

(function() {
    'use strict';

    var main            = global.cloudcmd.main,
        DIR             = main.DIR,
        SRVDIR          = main.SRVDIR,

        io              = main.require('socket.io'),
        update          = main.srvrequire('update'),
        exec            = main.child_process.exec,
        Util            = main.util,
        path            = main.path,
        mainpackage     = main.mainpackage,
        equalPart       = Util.isContainStrAtBegin,
        CLOUDCMD        = mainpackage.name,
        ClientFuncs     = [],
        ClientDirs      = [],
        OnMessageFuncs  = [],
        INFO_LOG_LEVEL  = 2,
        ENV             = process.env,
        WIN32           = main.WIN32,
        HELP            = {
            stdout  : CLOUDCMD + ' exit     \n' +
                      CLOUDCMD + ' update   \n',
        },

        /* windows commands thet require
         * unicode charset on locales
         * different then English
         */
        Win32Commands   = ['ASSOC', 'AT', 'ATTRIB', 'BREAK', 'CACLS', 'CALL',
                            'CD', 'CHCP', 'CHDIR', 'CHKDSK', 'CHKNTFS', 'CLS',
                            'CMD', 'COLOR', 'COMP', 'COMPACT', 'CONVERT', 'COPY',
                            'DATE', 'DEL', 'DIR', 'DISKCOMP', 'DISKCOPY', 'DOSKEY',
                            'ECHO', 'ENDLOCAL', 'ERASE', 'EXIT', 'FC', 'FIND',
                            'FINDSTR', 'FOR', 'FORMAT', 'FTYPE', 'GOTO', 'GRAFTABL',
                            'HELP', 'IF', 'LABEL', 'MD', 'MKDIR', 'MODE', 'MORE',
                            'MOVE', 'PATH', 'PAUSE', 'POPD', 'PRINT', 'PROMPT',
                            'PUSHD', 'RD', 'RECOVER', 'REM', 'REN', 'RENAME',
                            'REPLACE', 'RMDIR', 'SET', 'SETLOCAL', 'SHIFT', 'SORT',
                            'START', 'SUBST', 'TIME', 'TITLE', 'TREE', 'TYPE',
                            'VER', 'VERIFY', 'VOL', 'XCOPY'];

    /**
     * function listen on servers port
     * @pServer {Object} started server object
     */
    exports.listen = function(pServer) {
        var lRet, lConnNum, lMsg, lConn_func;

        if (io) {
            io          = io.listen(pServer);
            lConnNum    = 0;

            io.set('log level', INFO_LOG_LEVEL);

            /*
             * on Win7 application is crashing,
             * when options below is used.
             *
             * https://github.com/LearnBoost/socket.io/issues/1314
             *
             */
            if (!WIN32) {
                io.enable('browser client minification');
                io.enable('browser client gzip');
                io.enable('browser client etag');
            }

            io.set('transports', [
              'websocket',
              'htmlfile',
              'xhr-polling',
              'jsonp-polling'
            ]);

            lRet = io.sockets.on('connection', function (socket) {
                ++lConnNum;

                if(!OnMessageFuncs[lConnNum]) {
                    lMsg    = log(lConnNum, 'connected\n');

                    jsonSend(socket, {
                        stdout : lMsg
                    });

                    OnMessageFuncs[lConnNum]    = onMessage(lConnNum, socket);
                    lConn_func                  = OnMessageFuncs[lConnNum];

                    socket.on('message', lConn_func);
                    socket.on('disconnect', Util.call(disconnect, lConnNum));
                } else {
                    lMsg = log(lConnNum, ' in use. Reconnecting...');

                    jsonSend(socket, {
                        stdout: lMsg
                    });

                    socket.disconnect();
                }

            });
        }

        return lRet;
    };

    function disconnect(pParams) {
        var lConnNum, lRet = Util.checkObj(pParams, ['params']);

        if(lRet) {
            lConnNum = pParams.params;
            OnMessageFuncs  [lConnNum]  =
            ClientFuncs     [lConnNum]  = null;

            log(lConnNum, 'disconnected');
        }

    }

    /**
     * function gets onMessage function
     * that execute needed command
     *
     * @param pConnNum, pSocket
     */
    function onMessage(pConnNum, pSocket) {
        return function(pCommand) {
            var lMsg, lWinCommand, lExec_func, firstChar,
                connName,
                lError, lRet, lExecSymbols, isContain,
                dir, options = {};

            dir = ClientDirs[pConnNum];

            if (!dir)
                dir = ClientDirs[pConnNum] = DIR;

            connName = '#' + pConnNum + ': ';
            Util.log(connName + pCommand);

            if (equalPart(pCommand, CLOUDCMD))
                lRet = onCloudCmd(pCommand, function(json) {
                     jsonSend(pSocket, json);
                });
            else if (equalPart(pCommand, 'cd '))  {
                lRet = true;

                onCD(pCommand, dir, function(json) {
                    var error   = json.stderr,
                        stdout  = json.stdout;

                    if (error)
                        jsonSend(pSocket, json);
                    else
                        ClientDirs[pConnNum] = stdout;
                });
            }

            if (!lRet) {
                /* if we on windows and command is build in
                 * change code page to unicode becouse
                 * windows use unicode on non English versions
                 */
                if(WIN32) {
                    lWinCommand     = pCommand.toUpperCase();

                    if (Win32Commands.indexOf(lWinCommand) >= 0)
                        pCommand    = 'chcp 65001 |' + pCommand;
                }

                if(!ClientFuncs[pConnNum])
                    ClientFuncs[pConnNum] = getExec(function(json, pError, pStderr) {
                        log(pConnNum, pError, 'error');
                        log(pConnNum, pStderr, 'stderror');

                        jsonSend(pSocket, json);
                    });

                lExec_func      = ClientFuncs[pConnNum];
                lExecSymbols    = ['*', '&', '{', '}', '|', '\'', '"'];
                isContain       = Util.isContainStr(pCommand, lExecSymbols);
                firstChar       = pCommand[0];
                options.cwd     = dir;

                if (firstChar === '#') {
                    pCommand    = pCommand.slice(1);
                    pCommand    = connName + pCommand;
                    pCommand    = Util.addNewLine(pCommand);

                    lMsg    = Util.stringifyJSON({
                        stdout: pCommand
                    });

                    io.sockets.emit('message', lMsg);
                } else if (WIN32 || firstChar === ' ' || isContain)
                    exec(pCommand, options, lExec_func);
                else
                    getSpawn(pCommand, options, function(json) {
                        jsonSend(pSocket, json);
                    });
            }
        };
    }

    /**
     * function send result of command to client
     * @param pSocket
     */
    function getExec(callback) {
        return function(pError, pStdout, pStderr) {
            var lErrorStr, lExecStr, lExec,
                lError          = pStderr || pError;

            if (lError) {
                if (Util.isString(lError))
                    lErrorStr   = lError;
                else
                    lErrorStr   = lError.toString();

                lErrorStr = Util.addNewLine(lErrorStr);
            }

            lExec               = {
                stdout : pStdout,
                stderr : lErrorStr || lError
            };

            Util.exec(callback, lExec, pError, pStderr);
        };
    }

    function getSpawn(pCommand, options, callback) {
        var send, cmd, spawn,
            args    = pCommand.split(' ');

        pCommand    = args.shift();

        spawn       = main.child_process.spawn;
        Util.tryCatchLog(function() {
            cmd         = spawn(pCommand, args, options);
        });

        if (cmd) {
            send        = function(data, isError) {
                var lExec               = {},
                    msg                 = data.toString();

                if (isError)
                    lExec.stderr    = msg;
                else
                    lExec.stdout    = msg;

                Util.exec(callback, lExec);
            };

            cmd.stdout.on('data', send);

            cmd.stderr.on('data', function(data) {
                send(data, true);
            });

            cmd.on('error', Util.retFalse);
        }
    }

    function onCloudCmd(pCommand, callback) {
        var lRet;

        pCommand = Util.removeStr(pCommand, CLOUDCMD);

        if (!equalPart(pCommand, ' ')) {
            lRet = true;
            Util.exec(callback, HELP);
        }
        else {
            pCommand = Util.removeStr(pCommand, ' ');

            if (equalPart(pCommand, 'update') && update) {
                lRet = true;
                update.get();

                Util.exec(callback, {
                    stdout: Util.addNewLine('update: ok')
                });
            }

            if (Util.strCmp(pCommand, 'exit'))
                process.exit();
        }

        return lRet;
    }

    function onCD(pCommand, currDir, callback) {
        var dir,
            getDir      = WIN32 ? 'chdir' : 'pwd',
            paramDir    = Util.removeStr(pCommand, 'cd ');

        if (equalPart(paramDir, ['/', '~']))
            dir = paramDir;
        else
            dir = path.join(currDir, paramDir);

        exec('cd ' + dir + ' && ' + getDir, function (error, stdout, stderr) {
            var lRet,
                lMsg    = '',
                lError = error || stderr;

            if (lError) {
                lError  = Util.stringifyJSON(lError);
                lMsg    = lError;
            }

            Util.exec(callback, {
                stderr  : lMsg,
                stdout  : Util.rmNewLine(stdout)
            });
        });
    }

    function log(pConnNum, pStr, pType) {
        var lRet,
            lType       = ' ';

        if (pStr) {

            if (pType)
                lType  += pType + ':';

            lRet        = 'client #' + pConnNum + lType + pStr;

            Util.log(lRet);
        }

        return lRet;
    }

    function jsonSend(socket, json) {
        var msg = Util.stringifyJSON(json);
        socket.send(msg);
    }
})();
<commit_msg>fix(socket) prevent memory leak<commit_after>/* module make possible connectoin thru socket.io on a server */

(function() {
    'use strict';

    var main            = global.cloudcmd.main,
        DIR             = main.DIR,
        SRVDIR          = main.SRVDIR,

        io              = main.require('socket.io'),
        update          = main.srvrequire('update'),
        exec            = main.child_process.exec,
        Util            = main.util,
        path            = main.path,
        mainpackage     = main.mainpackage,
        equalPart       = Util.isContainStrAtBegin,
        CLOUDCMD        = mainpackage.name,
        ClientFuncs     = [],
        ClientDirs      = [],
        OnMessageFuncs  = [],
        INFO_LOG_LEVEL  = 2,
        ENV             = process.env,
        WIN32           = main.WIN32,
        HELP            = {
            stdout  : CLOUDCMD + ' exit     \n' +
                      CLOUDCMD + ' update   \n',
        },

        /* windows commands thet require
         * unicode charset on locales
         * different then English
         */
        Win32Commands   = ['ASSOC', 'AT', 'ATTRIB', 'BREAK', 'CACLS', 'CALL',
                            'CD', 'CHCP', 'CHDIR', 'CHKDSK', 'CHKNTFS', 'CLS',
                            'CMD', 'COLOR', 'COMP', 'COMPACT', 'CONVERT', 'COPY',
                            'DATE', 'DEL', 'DIR', 'DISKCOMP', 'DISKCOPY', 'DOSKEY',
                            'ECHO', 'ENDLOCAL', 'ERASE', 'EXIT', 'FC', 'FIND',
                            'FINDSTR', 'FOR', 'FORMAT', 'FTYPE', 'GOTO', 'GRAFTABL',
                            'HELP', 'IF', 'LABEL', 'MD', 'MKDIR', 'MODE', 'MORE',
                            'MOVE', 'PATH', 'PAUSE', 'POPD', 'PRINT', 'PROMPT',
                            'PUSHD', 'RD', 'RECOVER', 'REM', 'REN', 'RENAME',
                            'REPLACE', 'RMDIR', 'SET', 'SETLOCAL', 'SHIFT', 'SORT',
                            'START', 'SUBST', 'TIME', 'TITLE', 'TREE', 'TYPE',
                            'VER', 'VERIFY', 'VOL', 'XCOPY'];

    /**
     * function listen on servers port
     * @pServer {Object} started server object
     */
    exports.listen = function(pServer) {
        var lRet, lConnNum, lMsg, lConn_func;

        if (io) {
            io          = io.listen(pServer);
            lConnNum    = 0;

            io.set('log level', INFO_LOG_LEVEL);

            /*
             * on Win7 application is crashing,
             * when options below is used.
             *
             * https://github.com/LearnBoost/socket.io/issues/1314
             *
             */
            if (!WIN32) {
                io.enable('browser client minification');
                io.enable('browser client gzip');
                io.enable('browser client etag');
            }

            io.set('transports', [
              'websocket',
              'htmlfile',
              'xhr-polling',
              'jsonp-polling'
            ]);

            lRet = io.sockets.on('connection', function (socket) {
                ++lConnNum;

                if(!OnMessageFuncs[lConnNum]) {
                    lMsg    = log(lConnNum, 'connected\n');

                    jsonSend(socket, {
                        stdout : lMsg
                    });

                    OnMessageFuncs[lConnNum]    = onMessage(lConnNum, socket);
                    lConn_func                  = OnMessageFuncs[lConnNum];

                    socket.on('message', lConn_func);
                    socket.on('disconnect', Util.call(disconnect, lConnNum));
                } else {
                    lMsg = log(lConnNum, ' in use. Reconnecting...');

                    jsonSend(socket, {
                        stdout: lMsg
                    });

                    socket.disconnect();
                }

            });
        }

        return lRet;
    };

    function disconnect(pParams) {
        var lConnNum, lRet = Util.checkObj(pParams, ['params']);

        if(lRet) {
            lConnNum = pParams.params;
            OnMessageFuncs  [lConnNum]  =
            ClientFuncs     [lConnNum]  = null;

            log(lConnNum, 'disconnected');
        }

    }

    /**
     * function gets onMessage function
     * that execute needed command
     *
     * @param pConnNum, pSocket
     */
    function onMessage(pConnNum, pSocket) {
        return function(pCommand) {
            var lMsg, lWinCommand, lExec_func, firstChar,
                connName,
                lError, lRet, lExecSymbols, isContain,
                dir, options = {};

            dir = ClientDirs[pConnNum];

            if (!dir)
                dir = ClientDirs[pConnNum] = DIR;

            connName = '#' + pConnNum + ': ';
            Util.log(connName + pCommand);

            if (equalPart(pCommand, CLOUDCMD))
                lRet = onCloudCmd(pCommand, function(json) {
                     jsonSend(pSocket, json);
                });
            else if (equalPart(pCommand, 'cd '))  {
                lRet = true;

                onCD(pCommand, dir, function(json) {
                    var error   = json.stderr,
                        stdout  = json.stdout;

                    if (error)
                        jsonSend(pSocket, json);
                    else
                        ClientDirs[pConnNum] = stdout;
                });
            }

            if (!lRet) {
                /* if we on windows and command is build in
                 * change code page to unicode becouse
                 * windows use unicode on non English versions
                 */
                if(WIN32) {
                    lWinCommand     = pCommand.toUpperCase();

                    if (Win32Commands.indexOf(lWinCommand) >= 0)
                        pCommand    = 'chcp 65001 |' + pCommand;
                }

                if(!ClientFuncs[pConnNum])
                    ClientFuncs[pConnNum] = getExec(function(json, pError, pStderr) {
                        log(pConnNum, pError, 'error');
                        log(pConnNum, pStderr, 'stderror');

                        jsonSend(pSocket, json);
                    });

                lExec_func      = ClientFuncs[pConnNum];
                lExecSymbols    = ['*', '&', '{', '}', '|', '\'', '"'];
                isContain       = Util.isContainStr(pCommand, lExecSymbols);
                firstChar       = pCommand[0];
                options.cwd     = dir;

                if (firstChar === '#') {
                    pCommand    = pCommand.slice(1);
                    pCommand    = connName + pCommand;
                    pCommand    = Util.addNewLine(pCommand);

                    lMsg    = Util.stringifyJSON({
                        stdout: pCommand
                    });

                    io.sockets.emit('message', lMsg);
                } else if (WIN32 || firstChar === ' ' || isContain)
                    exec(pCommand, options, lExec_func);
                else
                    getSpawn(pCommand, options, function(json) {
                        jsonSend(pSocket, json);
                    });
            }
        };
    }

    /**
     * function send result of command to client
     * @param pSocket
     */
    function getExec(callback) {
        return function(pError, pStdout, pStderr) {
            var lErrorStr, lExecStr, lExec,
                lError          = pStderr || pError;

            if (lError) {
                if (Util.isString(lError))
                    lErrorStr   = lError;
                else
                    lErrorStr   = lError.toString();

                lErrorStr = Util.addNewLine(lErrorStr);
            }

            lExec               = {
                stdout : pStdout,
                stderr : lErrorStr || lError
            };

            Util.exec(callback, lExec, pError, pStderr);
        };
    }

    function getSpawn(pCommand, options, callback) {
        var send, cmd, spawn,
            args    = pCommand.split(' ');

        pCommand    = args.shift();

        spawn       = main.child_process.spawn;
        Util.tryCatchLog(function() {
            cmd         = spawn(pCommand, args, options);
        });

        if (cmd) {
            send        = function(data, isError) {
                var lExec               = {},
                    msg                 = data.toString();

                if (isError)
                    lExec.stderr    = msg;
                else
                    lExec.stdout    = msg;

                Util.exec(callback, lExec);
            };

            cmd.stdout.on('data', send);

            cmd.stderr.on('data', function(data) {
                send(data, true);
            });

            cmd.on('error', Util.retFalse);
            cmd.on('close', function (code) {
                cmd = null;
            });
        }
    }

    function onCloudCmd(pCommand, callback) {
        var lRet;

        pCommand = Util.removeStr(pCommand, CLOUDCMD);

        if (!equalPart(pCommand, ' ')) {
            lRet = true;
            Util.exec(callback, HELP);
        }
        else {
            pCommand = Util.removeStr(pCommand, ' ');

            if (equalPart(pCommand, 'update') && update) {
                lRet = true;
                update.get();

                Util.exec(callback, {
                    stdout: Util.addNewLine('update: ok')
                });
            }

            if (Util.strCmp(pCommand, 'exit'))
                process.exit();
        }

        return lRet;
    }

    function onCD(pCommand, currDir, callback) {
        var dir,
            getDir      = WIN32 ? 'chdir' : 'pwd',
            paramDir    = Util.removeStr(pCommand, 'cd ');

        if (equalPart(paramDir, ['/', '~']))
            dir = paramDir;
        else
            dir = path.join(currDir, paramDir);

        exec('cd ' + dir + ' && ' + getDir, function (error, stdout, stderr) {
            var lRet,
                lMsg    = '',
                lError = error || stderr;

            if (lError) {
                lError  = Util.stringifyJSON(lError);
                lMsg    = lError;
            }

            Util.exec(callback, {
                stderr  : lMsg,
                stdout  : Util.rmNewLine(stdout)
            });
        });
    }

    function log(pConnNum, pStr, pType) {
        var lRet,
            lType       = ' ';

        if (pStr) {

            if (pType)
                lType  += pType + ':';

            lRet        = 'client #' + pConnNum + lType + pStr;

            Util.log(lRet);
        }

        return lRet;
    }

    function jsonSend(socket, json) {
        var msg = Util.stringifyJSON(json);
        socket.send(msg);
    }
})();
<|endoftext|>


<commit_before>

//-------------------------------------------------------+
//  Sherdog MMA API
//  sherdog.getFighter(url, callback(data));
//-------------------------------------------------------+

var request = require("request");
var cheerio = require("cheerio");

//-------------------------------------------------------+
//  Get Fighter Profile
//-------------------------------------------------------+

module.exports.getFighter = function(url, callback) {
  request(url, function(error, response, html) {
    if (!error && response.statusCode == 200) {
      var $ = cheerio.load(html);

      //----------------------------------+
      //  JSON object for Fighter
      //----------------------------------+
      var fighter = {
        name: "",
        nickname: "",
        age: "",
        birthday: "",
        locality: "",
        nationality: "",
        association: "",
        height: "",
        weight: "",
        weight_class: "",
        image_url: "",
        wins: {
          total: 0,
          knockouts: 0,
          submissions: 0,
          decisions: 0,
          others: 0
        },
        losses: {
          total: 0,
          knockouts: 0,
          submissions: 0,
          decisions: 0,
          others: 0
        },
        no_contests: 0,
        fights: []
      };

      // Fighter name, nickname
      $('h1[itemprop="name"]').filter(function() {
        var el = $(this);
        name = el.find('span.fn').text();
        nickname = el.find('span.nickname').text();
        fighter.name = name;
        fighter.nickname = nickname.replace(/['"]+/g, '');
      });
      // Fighter image
      fighter.image_url = $(".profile_image.photo").attr("src");

      // Fighter bio
      $('.bio').filter(function() {
        var el = $(this);
        age = el.find('.item.birthday strong').text();
        birthday = el.find('span[itemprop="birthDate"]').text();
        locality = el.find('span[itemprop="addressLocality"]').text();
        nationality = el.find('strong[itemprop="nationality"]').text();
        association = el.find('.item.association span[itemprop="name"]').text();
        height = el.find('.item.height strong').text();
        weight = el.find('.item.weight strong').text();
        weight_class = el.find('.item.wclass strong').text();
        fighter.age = age.slice(5);
        fighter.birthday = birthday;
        fighter.locality = locality;
        fighter.nationality = nationality;
        fighter.association = association;
        fighter.height = height;
        fighter.weight = weight;
        fighter.weight_class = weight_class;
      });

      // Fighter record
      $('.record .count_history').filter(function() {
        var el = $(this);
        var wins = el.find('.left_side .bio_graph').first();
        var winsByKnockout = wins.find('.graph_tag:nth-child(3)');
        var winsBySubmission = wins.find('.graph_tag:nth-child(5)');
        var winsByDecision = wins.find('.graph_tag:nth-child(7)');
        var winsByOther = wins.find('.graph_tag:nth-child(9)');
        var losses = el.find('.left_side .bio_graph.loser');
        var lossesByKnockout = losses.find('.graph_tag:nth-child(3)');
        var lossesBySubmission = losses.find('.graph_tag:nth-child(5)');
        var lossesByDecision = losses.find('.graph_tag:nth-child(7)');
        var lossesByOther = losses.find('.graph_tag:nth-child(9)');
        var noContests = el.find('.right_side .bio_graph');
        var getTotal = function(el) { return parseInt(el.text().split(' ')[0] || 0); }
        var getPercent = function(el) { return el.find('em').text().split('%')[0]; }

        wins_total = parseInt(wins.find('.card .counter').text());
        losses_total = parseInt(losses.find('.counter').text());
        no_contests_total = parseInt(noContests.find('.counter').text());
        fighter.wins.total = wins_total;
        fighter.losses.total = losses_total;
        fighter.no_contests = no_contests_total;
        fighter.wins.knockouts = getTotal(winsByKnockout);
        fighter.wins.submissions = getTotal(winsBySubmission);
        fighter.wins.decisions = getTotal(winsByDecision);
        fighter.wins.others = getTotal(winsByOther);
        fighter.losses.knockouts = getTotal(lossesByKnockout);
        fighter.losses.submissions = getTotal(lossesBySubmission);
        fighter.losses.decisions = getTotal(lossesByDecision);
      });

      // Fighter Fight History
      $('.module.fight_history tr:not(.table_head)').each(function() {
        var el = $(this);
        result = el.find('td:nth-child(1) .final_result').text();
        opponent_name = el.find('td:nth-child(2) a').text();
        opponent_url = el.find('td:nth-child(2) a').attr('href');
        event_name = el.find('td:nth-child(3) a').text();
        event_url = el.find('td:nth-child(3) a').attr('href');
        event_date = el.find('td:nth-child(3) .sub_line').text();
        method = el.find('td:nth-child(4)').text().split(/\)(.*)/)[0] + ")";
        referee = el.find('td:nth-child(4) .sub_line').text();
        round = el.find('td:nth-child(5)').text();
        time = el.find('td:nth-child(6)').text();
        //----------------------------------+
        //  JSON object for Fight
        //----------------------------------+
        var fight = {
          name: event_name,
          date: event_date,
          url: event_url,
          result: result,
          method: method,
          referee: referee,
          round: round,
          time: time,
          opponent: opponent_name
        };

        if (result !== "") {
          fighter.fights.push(fight);
        }
      });

      callback(fighter);
    }
  });
}

<commit_msg>fix fighter name values<commit_after>

//-------------------------------------------------------+
//  Sherdog MMA API
//  sherdog.getFighter(url, callback(data));
//-------------------------------------------------------+

var request = require("request");
var cheerio = require("cheerio");

//-------------------------------------------------------+
//  Get Fighter Profile
//-------------------------------------------------------+

module.exports.getFighter = function(url, callback) {
  request(url, function(error, response, html) {
    if (!error && response.statusCode == 200) {
      var $ = cheerio.load(html);

      //----------------------------------+
      //  JSON object for Fighter
      //----------------------------------+
      var fighter = {
        name: "",
        nickname: "",
        age: "",
        birthday: "",
        locality: "",
        nationality: "",
        association: "",
        height: "",
        weight: "",
        weight_class: "",
        image_url: "",
        wins: {
          total: 0,
          knockouts: 0,
          submissions: 0,
          decisions: 0,
          others: 0
        },
        losses: {
          total: 0,
          knockouts: 0,
          submissions: 0,
          decisions: 0,
          others: 0
        },
        no_contests: 0,
        fights: []
      };

      // Fighter name, nickname
      $('.bio_fighter').filter(function() {
        var el = $(this);
        name = el.find('span.fn').text();
        nickname = el.find('span.nickname').text();
        fighter.name = name;
        fighter.nickname = nickname.replace(/['"]+/g, '');
      });
      // Fighter image
      fighter.image_url = $(".profile_image.photo").attr("src");

      // Fighter bio
      $('.bio').filter(function() {
        var el = $(this);
        age = el.find('.item.birthday strong').text();
        birthday = el.find('span[itemprop="birthDate"]').text();
        locality = el.find('span[itemprop="addressLocality"]').text();
        nationality = el.find('strong[itemprop="nationality"]').text();
        association = el.find('.item.association span[itemprop="name"]').text();
        height = el.find('.item.height strong').text();
        weight = el.find('.item.weight strong').text();
        weight_class = el.find('.item.wclass strong').text();
        fighter.age = age.slice(5);
        fighter.birthday = birthday;
        fighter.locality = locality;
        fighter.nationality = nationality;
        fighter.association = association;
        fighter.height = height;
        fighter.weight = weight;
        fighter.weight_class = weight_class;
      });

      // Fighter record
      $('.record .count_history').filter(function() {
        var el = $(this);
        var wins = el.find('.left_side .bio_graph').first();
        var winsByKnockout = wins.find('.graph_tag:nth-child(3)');
        var winsBySubmission = wins.find('.graph_tag:nth-child(5)');
        var winsByDecision = wins.find('.graph_tag:nth-child(7)');
        var winsByOther = wins.find('.graph_tag:nth-child(9)');
        var losses = el.find('.left_side .bio_graph.loser');
        var lossesByKnockout = losses.find('.graph_tag:nth-child(3)');
        var lossesBySubmission = losses.find('.graph_tag:nth-child(5)');
        var lossesByDecision = losses.find('.graph_tag:nth-child(7)');
        var lossesByOther = losses.find('.graph_tag:nth-child(9)');
        var noContests = el.find('.right_side .bio_graph');
        var getTotal = function(el) { return parseInt(el.text().split(' ')[0] || 0); }
        var getPercent = function(el) { return el.find('em').text().split('%')[0]; }

        wins_total = parseInt(wins.find('.card .counter').text());
        losses_total = parseInt(losses.find('.counter').text());
        no_contests_total = parseInt(noContests.find('.counter').text());
        fighter.wins.total = wins_total;
        fighter.losses.total = losses_total;
        fighter.no_contests = no_contests_total;
        fighter.wins.knockouts = getTotal(winsByKnockout);
        fighter.wins.submissions = getTotal(winsBySubmission);
        fighter.wins.decisions = getTotal(winsByDecision);
        fighter.wins.others = getTotal(winsByOther);
        fighter.losses.knockouts = getTotal(lossesByKnockout);
        fighter.losses.submissions = getTotal(lossesBySubmission);
        fighter.losses.decisions = getTotal(lossesByDecision);
      });

      // Fighter Fight History
      $('.module.fight_history tr:not(.table_head)').each(function() {
        var el = $(this);
        result = el.find('td:nth-child(1) .final_result').text();
        opponent_name = el.find('td:nth-child(2) a').text();
        opponent_url = el.find('td:nth-child(2) a').attr('href');
        event_name = el.find('td:nth-child(3) a').text();
        event_url = el.find('td:nth-child(3) a').attr('href');
        event_date = el.find('td:nth-child(3) .sub_line').text();
        method = el.find('td:nth-child(4)').text().split(/\)(.*)/)[0] + ")";
        referee = el.find('td:nth-child(4) .sub_line').text();
        round = el.find('td:nth-child(5)').text();
        time = el.find('td:nth-child(6)').text();
        //----------------------------------+
        //  JSON object for Fight
        //----------------------------------+
        var fight = {
          name: event_name,
          date: event_date,
          url: event_url,
          result: result,
          method: method,
          referee: referee,
          round: round,
          time: time,
          opponent: opponent_name
        };

        if (result !== "") {
          fighter.fights.push(fight);
        }
      });

      callback(fighter);
    }
  });
}

<|endoftext|>


<commit_before>/**
 * @depend util/core.js
 * @depend extend.js
 * @depend collection.js
 * @depend util/fake_timers.js
 * @depend util/fake_server_with_clock.js
 */
/**
 * Manages fake collections as well as fake utilities such as Sinon's
 * timers and fake XHR implementation in one convenient object.
 *
 * @author Christian Johansen (christian@cjohansen.no)
 * @license BSD
 *
 * Copyright (c) 2010-2013 Christian Johansen
 */
"use strict";

(function () {
    function makeApi(sinon) {
        var push = [].push;

        function exposeValue(sandbox, config, key, value) {
            if (!value) {
                return;
            }

            if (config.injectInto && !(key in config.injectInto)) {
                config.injectInto[key] = value;
                sandbox.injectedKeys.push(key);
            } else {
                push.call(sandbox.args, value);
            }
        }

        function prepareSandboxFromConfig(config) {
            var sandbox = sinon.create(sinon.sandbox);

            if (config.useFakeServer) {
                if (typeof config.useFakeServer == "object") {
                    sandbox.serverPrototype = config.useFakeServer;
                }

                sandbox.useFakeServer();
            }

            if (config.useFakeTimers) {
                if (typeof config.useFakeTimers == "object") {
                    sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
                } else {
                    sandbox.useFakeTimers();
                }
            }

            return sandbox;
        }

        sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
            useFakeTimers: function useFakeTimers() {
                this.clock = sinon.useFakeTimers.apply(sinon, arguments);

                return this.add(this.clock);
            },

            serverPrototype: sinon.fakeServer,

            useFakeServer: function useFakeServer() {
                var proto = this.serverPrototype || sinon.fakeServer;

                if (!proto || !proto.create) {
                    return null;
                }

                this.server = proto.create();
                return this.add(this.server);
            },

            inject: function (obj) {
                sinon.collection.inject.call(this, obj);

                if (this.clock) {
                    obj.clock = this.clock;
                }

                if (this.server) {
                    obj.server = this.server;
                    obj.requests = this.server.requests;
                }

                obj.match = sinon.match;

                return obj;
            },

            restore: function () {
                sinon.collection.restore.apply(this, arguments);
                this.restoreContext();
            },

            restoreContext: function () {
                if (this.injectedKeys) {
                    for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
                        delete this.injectInto[this.injectedKeys[i]];
                    }
                    this.injectedKeys = [];
                }
            },

            create: function (config) {
                if (!config) {
                    return sinon.create(sinon.sandbox);
                }

                var sandbox = prepareSandboxFromConfig(config);
                sandbox.args = sandbox.args || [];
                sandbox.injectedKeys = [];
                sandbox.injectInto = config.injectInto;
                var prop, value, exposed = sandbox.inject({});

                if (config.properties) {
                    for (var i = 0, l = config.properties.length; i < l; i++) {
                        prop = config.properties[i];
                        value = exposed[prop] || prop == "sandbox" && sandbox;
                        exposeValue(sandbox, config, prop, value);
                    }
                } else {
                    exposeValue(sandbox, config, "sandbox", value);
                }

                return sandbox;
            },

            match: sinon.match
        });

        sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;

        return sinon.sandbox;
    }

    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;

    function loadDependencies(require, exports, module) {
        var sinon = require("./util/core");
        require("./util/fake_server");
        require("./util/fake_timers");
        require("./collection");
        module.exports = makeApi(sinon);
    }

    if (isAMD) {
        define(loadDependencies);
    } else if (isNode) {
        loadDependencies(require, module.exports, module);
    } else if (!sinon) {
        return;
    } else {
        makeApi(sinon);
    }
}());
<commit_msg>Fix #633. Use a try/catch when deleting a property in IE8.<commit_after>/**
 * @depend util/core.js
 * @depend extend.js
 * @depend collection.js
 * @depend util/fake_timers.js
 * @depend util/fake_server_with_clock.js
 */
/**
 * Manages fake collections as well as fake utilities such as Sinon's
 * timers and fake XHR implementation in one convenient object.
 *
 * @author Christian Johansen (christian@cjohansen.no)
 * @license BSD
 *
 * Copyright (c) 2010-2013 Christian Johansen
 */
"use strict";

(function () {
    function makeApi(sinon) {
        var push = [].push;

        function exposeValue(sandbox, config, key, value) {
            if (!value) {
                return;
            }

            if (config.injectInto && !(key in config.injectInto)) {
                config.injectInto[key] = value;
                sandbox.injectedKeys.push(key);
            } else {
                push.call(sandbox.args, value);
            }
        }

        function prepareSandboxFromConfig(config) {
            var sandbox = sinon.create(sinon.sandbox);

            if (config.useFakeServer) {
                if (typeof config.useFakeServer == "object") {
                    sandbox.serverPrototype = config.useFakeServer;
                }

                sandbox.useFakeServer();
            }

            if (config.useFakeTimers) {
                if (typeof config.useFakeTimers == "object") {
                    sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
                } else {
                    sandbox.useFakeTimers();
                }
            }

            return sandbox;
        }

        sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
            useFakeTimers: function useFakeTimers() {
                this.clock = sinon.useFakeTimers.apply(sinon, arguments);

                return this.add(this.clock);
            },

            serverPrototype: sinon.fakeServer,

            useFakeServer: function useFakeServer() {
                var proto = this.serverPrototype || sinon.fakeServer;

                if (!proto || !proto.create) {
                    return null;
                }

                this.server = proto.create();
                return this.add(this.server);
            },

            inject: function (obj) {
                sinon.collection.inject.call(this, obj);

                if (this.clock) {
                    obj.clock = this.clock;
                }

                if (this.server) {
                    obj.server = this.server;
                    obj.requests = this.server.requests;
                }

                obj.match = sinon.match;

                return obj;
            },

            restore: function () {
                sinon.collection.restore.apply(this, arguments);
                this.restoreContext();
            },

            restoreContext: function () {
                if (this.injectedKeys) {
                    for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
                        // Use a try/catch to delete a property in IE8
                        try {
                            delete this.injectInto[this.injectedKeys[i]];
                        } catch (e) {
                            this.injectInto[this.injectedKeys[i]] = undefined
                        }
                    }
                    this.injectedKeys = [];
                }
            },

            create: function (config) {
                if (!config) {
                    return sinon.create(sinon.sandbox);
                }

                var sandbox = prepareSandboxFromConfig(config);
                sandbox.args = sandbox.args || [];
                sandbox.injectedKeys = [];
                sandbox.injectInto = config.injectInto;
                var prop, value, exposed = sandbox.inject({});

                if (config.properties) {
                    for (var i = 0, l = config.properties.length; i < l; i++) {
                        prop = config.properties[i];
                        value = exposed[prop] || prop == "sandbox" && sandbox;
                        exposeValue(sandbox, config, prop, value);
                    }
                } else {
                    exposeValue(sandbox, config, "sandbox", value);
                }

                return sandbox;
            },

            match: sinon.match
        });

        sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;

        return sinon.sandbox;
    }

    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;

    function loadDependencies(require, exports, module) {
        var sinon = require("./util/core");
        require("./util/fake_server");
        require("./util/fake_timers");
        require("./collection");
        module.exports = makeApi(sinon);
    }

    if (isAMD) {
        define(loadDependencies);
    } else if (isNode) {
        loadDependencies(require, module.exports, module);
    } else if (!sinon) {
        return;
    } else {
        makeApi(sinon);
    }
}());
<|endoftext|>


<commit_before>/* global module, require */

var mergeTrees = require( 'broccoli-merge-trees' );
var path = require( 'path' );
var pickFiles = require( 'broccoli-static-compiler' );
var slComponentsPath = path.join( 'node_modules', 'sl-components' );

function SlComponents( project ) {
    this.project = project;
    this.name    = 'sl-components';
}

function unwatchedTree( dir ) {
    return {
        cleanup: function () {},
        read:    function () { return dir; }
    };
}

SlComponents.prototype.included = function included( app ) {
    this.app = app;

    app.import( 'vendor/bootstrap-datepicker/js/bootstrap-datepicker.js' );
    app.import( 'vendor/highcharts/highcharts.js' );
    app.import({
        'development': 'vendor/moment/moment.js',
        'production': 'vendor/moment/min/moment-with-langs.min.js'
    });
    app.import( 'vendor/select2/select2.min.js' );
    app.import({
        'development': 'vendor/sl-bootstrap/dist/js/sl-bootstrap.js',
        'production': 'vendor/sl-bootstrap/dist/js/sl-bootstrap.min.js'
    });
    app.import( 'vendor/typeahead.js/dist/typeahead.bundle.min.js' );
};

SlComponents.prototype.postprocessTree = function ( type, workingTree ) {
    var trees = mergeTrees([
        workingTree,
        pickFiles( path.join( slComponentsPath, 'vendor', 'fontawesome/fonts' ), {
            srcDir: '/',
            files: [
                'fontawesome-webfont.woff'
            ],
            destDir: '/fonts'
        }),
        pickFiles( path.join( slComponentsPath, 'public/assets/images' ), {
            srcDir: '/',
            files: [
                'spinner-dark.png',
                'spinner-light.png'
            ],
            destDir: '/assets/images'
        })
    ]);

    return trees;
};

SlComponents.prototype.treeFor = function treeFor( name ) {
    if ( name === 'app' ) {
        return pickFiles( path.join( slComponentsPath, 'app' ), {
            srcDir: '/',
            files: [
                'components/sl-*.js',
                'helpers/**/*.js',
                'mixins/**/*.js',
                'utils/**/*.js'
            ],
            destDir: '/'
        });
    }

    if ( name === 'styles' ) {
        return unwatchedTree( path.join( slComponentsPath, 'app/styles' ));
    }

    if ( name === 'templates' ) {
        return pickFiles( path.join( slComponentsPath, 'app/templates' ), {
            srcDir: '/',
            files: [
                'components/sl-*',
                'sl-grid/*',
                'sl-modal.hbs'
            ],
            destDir: '/'
        });
    }

    if ( name === 'vendor' ) {
        return pickFiles( path.join( slComponentsPath, 'vendor' ), {
            srcDir: '/',
            files: [
                'bootstrap-datepicker/less/datepicker3.less',
                'bootstrap-datepicker/js/bootstrap-datepicker.js',
                'fontawesome/less/*.less',
                'highcharts/highcharts.js',
                'moment/moment.js',
                'moment/min/moment-with-langs.min.js',
                'select2/select2.css',
                'select2/select2-bootstrap.css',
                'select2/select2.min.js',
                'sl-bootstrap/less/*.less',
                'sl-bootstrap/dist/js/sl-bootstrap.js',
                'sl-bootstrap/dist/js/sl-bootstrap.min.js',
                'typeahead.js/dist/typeahead.bundle.min.js'
            ],
            destDir: '/'
        });
    }
};

module.exports = SlComponents;
<commit_msg>Remove re-included Select2 CSS from lib file<commit_after>/* global module, require */

var mergeTrees = require( 'broccoli-merge-trees' );
var path = require( 'path' );
var pickFiles = require( 'broccoli-static-compiler' );
var slComponentsPath = path.join( 'node_modules', 'sl-components' );

function SlComponents( project ) {
    this.project = project;
    this.name    = 'sl-components';
}

function unwatchedTree( dir ) {
    return {
        cleanup: function () {},
        read:    function () { return dir; }
    };
}

SlComponents.prototype.included = function included( app ) {
    this.app = app;

    app.import( 'vendor/bootstrap-datepicker/js/bootstrap-datepicker.js' );
    app.import( 'vendor/highcharts/highcharts.js' );
    app.import({
        'development': 'vendor/moment/moment.js',
        'production': 'vendor/moment/min/moment-with-langs.min.js'
    });
    app.import( 'vendor/select2/select2.min.js' );
    app.import({
        'development': 'vendor/sl-bootstrap/dist/js/sl-bootstrap.js',
        'production': 'vendor/sl-bootstrap/dist/js/sl-bootstrap.min.js'
    });
    app.import( 'vendor/typeahead.js/dist/typeahead.bundle.min.js' );
};

SlComponents.prototype.postprocessTree = function ( type, workingTree ) {
    var trees = mergeTrees([
        workingTree,
        pickFiles( path.join( slComponentsPath, 'vendor', 'fontawesome/fonts' ), {
            srcDir: '/',
            files: [
                'fontawesome-webfont.woff'
            ],
            destDir: '/fonts'
        }),
        pickFiles( path.join( slComponentsPath, 'public/assets/images' ), {
            srcDir: '/',
            files: [
                'spinner-dark.png',
                'spinner-light.png'
            ],
            destDir: '/assets/images'
        })
    ]);

    return trees;
};

SlComponents.prototype.treeFor = function treeFor( name ) {
    if ( name === 'app' ) {
        return pickFiles( path.join( slComponentsPath, 'app' ), {
            srcDir: '/',
            files: [
                'components/sl-*.js',
                'helpers/**/*.js',
                'mixins/**/*.js',
                'utils/**/*.js'
            ],
            destDir: '/'
        });
    }

    if ( name === 'styles' ) {
        return unwatchedTree( path.join( slComponentsPath, 'app/styles' ));
    }

    if ( name === 'templates' ) {
        return pickFiles( path.join( slComponentsPath, 'app/templates' ), {
            srcDir: '/',
            files: [
                'components/sl-*',
                'sl-grid/*',
                'sl-modal.hbs'
            ],
            destDir: '/'
        });
    }

    if ( name === 'vendor' ) {
        return pickFiles( path.join( slComponentsPath, 'vendor' ), {
            srcDir: '/',
            files: [
                'bootstrap-datepicker/less/datepicker3.less',
                'bootstrap-datepicker/js/bootstrap-datepicker.js',
                'fontawesome/less/*.less',
                'highcharts/highcharts.js',
                'moment/moment.js',
                'moment/min/moment-with-langs.min.js',
                'select2/select2.min.js',
                'sl-bootstrap/less/*.less',
                'sl-bootstrap/dist/js/sl-bootstrap.js',
                'sl-bootstrap/dist/js/sl-bootstrap.min.js',
                'typeahead.js/dist/typeahead.bundle.min.js'
            ],
            destDir: '/'
        });
    }
};

module.exports = SlComponents;
<|endoftext|>


<commit_before>
var Memory = module.exports = function(config) {
	this.type = 'memory';
	this.data = {};
};
Memory.prototype = {

	get: function(key, done) {
		done(null, getValue(this, key));

		return this;
	},

	set: function(key, value, ttl, done) {
		this.data[key] = packageData(value, ttl);
		if(done) done(null, true);

		return this;
	},

	mget: function(keys, done) {
		var self = this,
			values = (keys||[]).map(function(key) {
				return getValue(self, key);
			});

		done(null, values);

		return this;
	},

	mset: function(hash, ttl, done) {

		var self = this;

		Object.keys(hash||{}).forEach(function(key) {
			self.data[key] = packageData(hash[key], ttl);
		});

		if(done) done(null, true);

		return this;
	},

	expire: function(key, ttl, done) {
		var expired = true,
			exists = key in this.data;

		// Adjust ttl or expire the key
		if(exists && ttl !== undefined) {
			this.data[key].expire = getExpiration(ttl);
		}else {
			expired = removeKey(this, key);
		}

		done(null, expired);

		return this;
	}

};

function getValue(cache, key) {
	var value = cache.data[key];

	if(isExpired(value)) {
		removeKey(cache, key);
		value = undefined;
	}

	return value && value.data;
}

function removeKey(cache, key) {
	var exists = key in cache.data;
	if(exists) delete cache.data[key];
	return exists;
}

function packageData(value, ttl) {
	var expire = null;
	if(ttl !== undefined) {
		expire = getExpiration(ttl);
	}
	return {
		expire: expire,
		data: value
	};
}

function getExpiration(ttl) {
	return Date.now() + (ttl^0 * 1000);
}

function isExpired(value) {
	return (value && value.expire) ? value.expire < Date.now() : false;
}
<commit_msg>Fixing order of operations issue<commit_after>
var Memory = module.exports = function(config) {
	this.type = 'memory';
	this.data = {};
};
Memory.prototype = {

	get: function(key, done) {
		done(null, getValue(this, key));

		return this;
	},

	set: function(key, value, ttl, done) {
		this.data[key] = packageData(value, ttl);
		if(done) done(null, true);

		return this;
	},

	mget: function(keys, done) {
		var self = this,
			values = (keys||[]).map(function(key) {
				return getValue(self, key);
			});

		done(null, values);

		return this;
	},

	mset: function(hash, ttl, done) {

		var self = this;

		Object.keys(hash||{}).forEach(function(key) {
			self.data[key] = packageData(hash[key], ttl);
		});

		if(done) done(null, true);

		return this;
	},

	expire: function(key, ttl, done) {
		var expired = true,
			exists = key in this.data;

		// Adjust ttl or expire the key
		if(exists && ttl !== undefined) {
			this.data[key].expire = getExpiration(ttl);
		}else {
			expired = removeKey(this, key);
		}

		done(null, expired);

		return this;
	}

};

function getValue(cache, key) {
	var value = cache.data[key];

	if(isExpired(value)) {
		removeKey(cache, key);
		value = undefined;
	}

	return value && value.data;
}

function removeKey(cache, key) {
	var exists = key in cache.data;
	if(exists) delete cache.data[key];
	return exists;
}

function packageData(value, ttl) {
	var expire = null;
	if(ttl !== undefined) {
		expire = getExpiration(ttl);
	}
	return {
		expire: expire,
		data: value
	};
}

function getExpiration(ttl) {
	return Date.now() + ((ttl^0) * 1000);
}

function isExpired(value) {
	return (value && value.expire) ? value.expire < Date.now() : false;
}
<|endoftext|>


<commit_before>var events = require("events");
var fs = require('fs');
var http = require('http');
var https = require('https');
var util = require('util');

var Promise = require('promise');
var Speaker = require('speaker');
var lame = require('lame');
var mpg123Util = require('node-mpg123-util');

/**
 * @param {string} uri
 * @constructor
 */
StupidPlayer = function(uri) {
	this._decoder = null;
	this._speaker = null;
	this._request = null;

	this._src = uri;

	this._onDecoderFormatted = this._onDecoderFormatted.bind(this);
	this._onDecoderClosed = this._onDecoderClosed.bind(this);
	this._onError = this._onError.bind(this);
};
util.inherits(StupidPlayer, events.EventEmitter);

/**
 * @return {Promise.<Format>}
 */
StupidPlayer.prototype.play = function() {
	var uri = this._src;
	if (this._isStream()) {
		return this.playStream(uri);
	} else {
		return this.playFile(uri);
	}
};

/**
 * @param {string} url
 * @return {Promise.<Format>}
 */
StupidPlayer.prototype.playStream = function(url) {
	return new Promise(function(resolve, reject) {
		var request = url.indexOf('https') === 0 ? https : http;

		this._request = request.get(url, function(res, req) {
			this._makeDecoder(res)
				.then(function(format) {
					resolve(format);
				});
		}.bind(this));

		this._request.once('error', this._onError);
	}.bind(this));
};

/**
 * @param {string} path
 * @return {Promise.<Format>}
 */
StupidPlayer.prototype.playFile = function(path) {
	return new Promise(function(resolve, reject) {
		var readStream = fs.createReadStream(path);

		readStream.once('error', this._onError);

		return this
			._makeDecoder(readStream)
			.then(function(format) {
				resolve(format);
			});
	}.bind(this));
};

/**
 *
 */
StupidPlayer.prototype.stop = function() {
	if (this._state !== this.state.STOP) {
		this._state = this.state.STOP;
		this._emit(this.EVENT_STOP);
		this.deinit();
	}
};

/**
 * @param {number} value 0..1
 * @return {Promise.<number>}
 */
StupidPlayer.prototype.setVolume = function(value) {
	return new Promise(function(resolve, reject) {
		var resolver = function() {
			resolve(value);
			this._emit(this.EVENT_VOLUME_CHANGE, value);
		}.bind(this);

		if (this._decoder) {
			mpg123Util.setVolume(this._decoder.mh, value);
			setTimeout(resolver, this.VOLUME_CHANGE_TIMEOUT);
		} else {
			reject(null);
		}
	}.bind(this));
};

/**
 * @return {?number} 0..1
 */
StupidPlayer.prototype.getVolume = function() {
	if (this._decoder) {
		return mpg123Util.getVolume(this._decoder.mh);
	} else {
		return null;
	}
};

/**
 *
 */
StupidPlayer.prototype.deinit = function() {
	this._closeConnection();
	if (this._speaker) {
		this._decoder.removeListener('error', this._onError);

		this._decoder.unpipe();
		this._speaker.end();

		this._speaker = null;
		this._decoder = null;
	}
};

/**
 *
 * @protected
 */
StupidPlayer.prototype._closeConnection = function() {
	if (this._request) {
		this._request.removeListener('error', this._onError);
		this._request.destroy();
		this._request = null;
	}
};

/**
 *
 * @return {boolean}
 * @protected
 */
StupidPlayer.prototype._isStream = function() {
	var src = this._src;
	return src.indexOf('http') === 0 || src.indexOf('https') === 0;
};

/**
 *
 * @param res
 * @return {Promise.<Format>}
 * @protected
 */
StupidPlayer.prototype._makeDecoder = function(res) {
	return new Promise(function(resolve, reject) {
		if (!this._isStream() || this._checkConnect(res, function() {})) {// todo need simple method
			this._decoder = new lame.Decoder();
			res.pipe(this._decoder);

			this._decoder.once('format', function(format) {
				this._onDecoderFormatted(format);
				resolve(format);
			}.bind(this));

			this._decoder.on('error', this._onError);

		} else {
			this._state = this.state.STOP;
			this._emit(this.EVENT_STOP);
		}
	}.bind(this));
};

/**
 *
 * @param format
 * @protected
 */
StupidPlayer.prototype._play = function(format) {
	if (this._state !== this.state.STOP) {
		this._speaker = new Speaker(format);

		this._emit(this.EVENT_START, this._isStream());
		this._state = this.state.PLAY;

		this._pipedDecoder = this._decoder.pipe(this._speaker);
		this._pipedDecoder.once('close', this._onDecoderClosed);
	}
};

/**
 *
 * @param res
 * @param callback
 * @return {boolean}
 * @protected
 */
StupidPlayer.prototype._checkConnect = function(res, callback) {
	var isOk = res.statusCode === 200;
	var isAudio = (res.headers['content-type'].indexOf('audio/mpeg') !== -1);
	if (!isOk) {
		callback(new Error('resource invalid'));
		return false;
	}
	if (!isAudio) {
		callback(new Error('resource type is unsupported'));
		return false;
	}
	return true;
};

/**
 * @param {string} event
 * @param {*?} opt_data
 * @protected
 */
StupidPlayer.prototype._emit = function(event, opt_data) {
//	console.log('stupid-player emit', event);
	this.emit(event, opt_data);
};

/**
 *
 * @param format
 * @protected
 */
StupidPlayer.prototype._onDecoderFormatted = function(format) {
	this._play(format);
};

/**
 *
 * @protected
 */
StupidPlayer.prototype._onDecoderClosed = function() {
	this.stop();
};

/**
 *
 * @param {string} error
 * @protected
 */
StupidPlayer.prototype._onError = function(error) {
	if (this._request) {
		this._request = null;
	} else {
		return;
	}
	this._emit(this.EVENT_ERROR, error);
};

/**
 *
 */
StupidPlayer.prototype._decoder;

/**
 *
 */
StupidPlayer.prototype._speaker;

/**
 *
 */
StupidPlayer.prototype._pipedDecoder;

/**
 * @type {string}
 */
StupidPlayer.prototype._src;

/**
 * @type {ClientRequest}
 */
StupidPlayer.prototype._request;

/**
 * @const {number}
 */
StupidPlayer.prototype.VOLUME_CHANGE_TIMEOUT = 300;

/**
 * @const {string}
 */
StupidPlayer.prototype.EVENT_START = 'start';

/**
 * @const {string}
 */
StupidPlayer.prototype.EVENT_STOP = 'stop';

/**
 * Fired with: {number} volume
 * @const {string}
 */
StupidPlayer.prototype.EVENT_VOLUME_CHANGE = 'volume-change';

/**
 * Fired with: string
 * @const {string}
 */
StupidPlayer.prototype.EVENT_ERROR = 'error';

/**
 * @enum {string}
 */
StupidPlayer.prototype.state = {
	PLAY: 'play',
	STOP: 'stop',
	PAUSE: 'pause'
};

module.exports = StupidPlayer;
<commit_msg>Set protected methods _playStream, _playFile, _deinit<commit_after>var events = require("events");
var fs = require('fs');
var http = require('http');
var https = require('https');
var util = require('util');

var Promise = require('promise');
var Speaker = require('speaker');
var lame = require('lame');
var mpg123Util = require('node-mpg123-util');

/**
 * @param {string} uri
 * @constructor
 */
StupidPlayer = function(uri) {
	this._decoder = null;
	this._speaker = null;
	this._request = null;

	this._src = uri;

	this._onDecoderFormatted = this._onDecoderFormatted.bind(this);
	this._onDecoderClosed = this._onDecoderClosed.bind(this);
	this._onError = this._onError.bind(this);
};
util.inherits(StupidPlayer, events.EventEmitter);

/**
 * @return {Promise.<Format>}
 */
StupidPlayer.prototype.play = function() {
	var uri = this._src;
	if (this._isStream()) {
		return this._playStream(uri);
	} else {
		return this._playFile(uri);
	}
};

/**
 * @param {string} url
 * @return {Promise.<Format>}
 * @protected
 */
StupidPlayer.prototype._playStream = function(url) {
	return new Promise(function(resolve, reject) {
		var request = url.indexOf('https') === 0 ? https : http;

		this._request = request.get(url, function(res, req) {
			this._makeDecoder(res)
				.then(function(format) {
					resolve(format);
				});
		}.bind(this));

		this._request.once('error', this._onError);
	}.bind(this));
};

/**
 * @param {string} path
 * @return {Promise.<Format>}
 * @protected
 */
StupidPlayer.prototype._playFile = function(path) {
	return new Promise(function(resolve, reject) {
		var readStream = fs.createReadStream(path);

		readStream.once('error', this._onError);

		return this
			._makeDecoder(readStream)
			.then(function(format) {
				resolve(format);
			});
	}.bind(this));
};

/**
 *
 */
StupidPlayer.prototype.stop = function() {
	if (this._state !== this.state.STOP) {
		this._state = this.state.STOP;
		this._emit(this.EVENT_STOP);
		this._deinit();
	}
};

/**
 * @param {number} value 0..1
 * @return {Promise.<number>}
 */
StupidPlayer.prototype.setVolume = function(value) {
	return new Promise(function(resolve, reject) {
		var resolver = function() {
			resolve(value);
			this._emit(this.EVENT_VOLUME_CHANGE, value);
		}.bind(this);

		if (this._decoder) {
			mpg123Util.setVolume(this._decoder.mh, value);
			setTimeout(resolver, this.VOLUME_CHANGE_TIMEOUT);
		} else {
			reject(null);
		}
	}.bind(this));
};

/**
 * @return {?number} 0..1
 */
StupidPlayer.prototype.getVolume = function() {
	if (this._decoder) {
		return mpg123Util.getVolume(this._decoder.mh);
	} else {
		return null;
	}
};

/**
 *
 * @protected
 */
StupidPlayer.prototype._deinit = function() {
	this._closeConnection();
	if (this._speaker) {
		this._decoder.removeListener('error', this._onError);

		this._decoder.unpipe();
		this._speaker.end();

		this._speaker = null;
		this._decoder = null;
	}
};

/**
 *
 * @protected
 */
StupidPlayer.prototype._closeConnection = function() {
	if (this._request) {
		this._request.removeListener('error', this._onError);
		this._request.destroy();
		this._request = null;
	}
};

/**
 *
 * @return {boolean}
 * @protected
 */
StupidPlayer.prototype._isStream = function() {
	var src = this._src;
	return src.indexOf('http') === 0 || src.indexOf('https') === 0;
};

/**
 *
 * @param res
 * @return {Promise.<Format>}
 * @protected
 */
StupidPlayer.prototype._makeDecoder = function(res) {
	return new Promise(function(resolve, reject) {
		if (!this._isStream() || this._checkConnect(res, function() {})) {// todo need simple method
			this._decoder = new lame.Decoder();
			res.pipe(this._decoder);

			this._decoder.once('format', function(format) {
				this._onDecoderFormatted(format);
				resolve(format);
			}.bind(this));

			this._decoder.on('error', this._onError);

		} else {
			this._state = this.state.STOP;
			this._emit(this.EVENT_STOP);
		}
	}.bind(this));
};

/**
 *
 * @param format
 * @protected
 */
StupidPlayer.prototype._play = function(format) {
	if (this._state !== this.state.STOP) {
		this._speaker = new Speaker(format);

		this._emit(this.EVENT_START, this._isStream());
		this._state = this.state.PLAY;

		this._pipedDecoder = this._decoder.pipe(this._speaker);
		this._pipedDecoder.once('close', this._onDecoderClosed);
	}
};

/**
 *
 * @param res
 * @param callback
 * @return {boolean}
 * @protected
 */
StupidPlayer.prototype._checkConnect = function(res, callback) {
	var isOk = res.statusCode === 200;
	var isAudio = (res.headers['content-type'].indexOf('audio/mpeg') !== -1);
	if (!isOk) {
		callback(new Error('resource invalid'));
		return false;
	}
	if (!isAudio) {
		callback(new Error('resource type is unsupported'));
		return false;
	}
	return true;
};

/**
 * @param {string} event
 * @param {*?} opt_data
 * @protected
 */
StupidPlayer.prototype._emit = function(event, opt_data) {
//	console.log('stupid-player emit', event);
	this.emit(event, opt_data);
};

/**
 *
 * @param format
 * @protected
 */
StupidPlayer.prototype._onDecoderFormatted = function(format) {
	this._play(format);
};

/**
 *
 * @protected
 */
StupidPlayer.prototype._onDecoderClosed = function() {
	this.stop();
};

/**
 *
 * @param {string} error
 * @protected
 */
StupidPlayer.prototype._onError = function(error) {
	if (this._request) {
		this._request = null;
	} else {
		return;
	}
	this._emit(this.EVENT_ERROR, error);
};

/**
 *
 */
StupidPlayer.prototype._decoder;

/**
 *
 */
StupidPlayer.prototype._speaker;

/**
 *
 */
StupidPlayer.prototype._pipedDecoder;

/**
 * @type {string}
 */
StupidPlayer.prototype._src;

/**
 * @type {ClientRequest}
 */
StupidPlayer.prototype._request;

/**
 * @const {number}
 */
StupidPlayer.prototype.VOLUME_CHANGE_TIMEOUT = 300;

/**
 * @const {string}
 */
StupidPlayer.prototype.EVENT_START = 'start';

/**
 * @const {string}
 */
StupidPlayer.prototype.EVENT_STOP = 'stop';

/**
 * Fired with: {number} volume
 * @const {string}
 */
StupidPlayer.prototype.EVENT_VOLUME_CHANGE = 'volume-change';

/**
 * Fired with: string
 * @const {string}
 */
StupidPlayer.prototype.EVENT_ERROR = 'error';

/**
 * @enum {string}
 */
StupidPlayer.prototype.state = {
	PLAY: 'play',
	STOP: 'stop',
	PAUSE: 'pause'
};

module.exports = StupidPlayer;
<|endoftext|>


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

'use strict';

var path = require('path');
var _ = require('lodash');
var fse = require('fs-extra');
var uuid = require('uuid');
var git = require('./gitutil');
var srMeta = require('./sysrevMeta');
var ku = require('../kutils');
var blank = {'name': '',
             'namespace': '',
             'id': '',
             'containerDefinitions': [],
             'topology': {'containers': {}}};

/**
 * maintains system commit log and history using nodegit
 * uses master branch only
 * need to be able to create a new repo on demand - for new system definition
 */
module.exports = function(options, logger) {

  var _meta;

  /**
   * ensures that system has all required files, and reads system.json
   */
  var initNscaleFiles = function(repoPath, doc) {
    fse.writeFileSync(path.join(repoPath, 'system.json'), JSON.stringify(doc, null, 2), 'utf8');
    fse.writeFileSync(path.join(repoPath, 'deployed.json'), '{"deployed": null}', 'utf8');
    fse.writeFileSync(path.join(repoPath, 'timeline.json'), '{"entries": []}', 'utf8');
    fse.writeFileSync(path.join(repoPath, '.gitignore'), 'workspace\nbuilds\n', 'utf8');
  };

  /**
   * timeline format
   * {
   *   entries: [{user: user, ts: new Date(), type: entryType, details: details},...
   * }
   */
  // TODO fix this - need to just do file append rather than read / write
  var writeTimeline = function(user, systemId, entryType, details) {
    var repoPath = _meta.repoPath(systemId);
    var timeline;
    var entry;

    timeline = fse.readFileSync(repoPath + '/timeline.json', 'utf8');
    timeline = JSON.parse(timeline);
    entry = {user: user, ts: new Date(), type: entryType, details: details};
    timeline.entries.push(entry);
    fse.writeFileSync(repoPath + '/timeline.json', JSON.stringify(timeline), 'utf8');
  };

  // TODO: fix this - don't want huge blocks of JSON need to partition up
  var getTimeline = function(systemId, cb) {
    var repoPath = _meta.repoPath(systemId);
    var timeline;

    timeline = fse.readFileSync(repoPath + '/timeline.json', 'utf8');
    timeline = JSON.parse(timeline);
    if (timeline.entries) {timeline.entries.reverse();}
    cb(null, timeline);
  };

  /**
   * make a commit to local git repository
   * TODO: implement seperate push functionality
   * TODO: replace with git hub id
   */
  var commit = function(user, systemId, message, cb) {
    logger.info('commiting revision: ' + systemId + ', ' + message);
    var repoPath = _meta.repoPath(systemId);
    git.commit(repoPath, ['system.json', 'timeline.json', 'deployed.json'], message, user.name, user.email, cb);
  };

  /**
   * create a new system repository
   */
  var createSystem = function(user, namespace, name, cwd, cb) {
    //var repoName = namespace + '_' + name;
    var repoName = name;
    var doc = _.extend({}, blank);
    var repoPath = path.join(cwd, repoName);

    doc.name = name;
    doc.namespace = namespace;
    doc.id = uuid.v4();

    if (!fse.existsSync(path.join(repoPath, 'system.json'))) {
      fse.mkdirpSync(repoPath);
      initNscaleFiles(repoPath, doc);
      git.createRepository(repoPath, ['system.json', 'deployed.json', 'timeline.json'], user.name, user.email, function(err) {
        if (err) { return cb(err); }
        _meta.register(user, namespace, name, repoName, cwd + '/' + repoName, doc.id, function(err) {
          writeTimeline(user, doc.id, 'create', 'system created');
          cb(err, {id: doc.id, err: err});
        });
      });
    }
    else {
      cb(null, { id: _meta.repoId(repoName), err: null});
    }
  };

  /**
   * create a new system by pulling from an existing repository
   *
   * var test1 = 'git@github.com:pelger/mlshack.git';
   * var test2 = 'https://github.com/pelger/mlshack.git';
   */
  var cloneSystem = function(user, url, cwd, cb) {
    var repoName;
    var repoPath;
    var doc;

    if (ku.checkGitUrl(url)) {
      repoName = ku.parseGitUrl(url).repo;
      repoPath = path.join(cwd, repoName);
      git.clone(url, repoPath, function(err) {
        if (err) { return cb(err); }
        if (fse.existsSync(path.join(repoPath, 'system.json'))) {
          doc = fse.readFileSync(path.join(repoPath, 'system.json'), 'utf8');
          try {
            doc = JSON.parse(doc);
          }
          catch (e) {
            return cb(new Error('invalid system: ' + e.message));
          }
        }
        else {
          doc = _.extend({}, blank);
          doc.name = repoName;
          doc.namespace = repoName;
          doc.id = uuid.v4();
          doc.remoteUrl = url;
          initNscaleFiles(repoPath, doc);
        }
        git.initClonedRepo(repoPath, ['system.json', 'deployed.json', 'timeline.json'], user.name, user.email, function(err) {
          if (err) { return cb(err); }
          // namespce and name parameters...
          _meta.register(user, doc.namespace, doc.name, repoName, repoPath, doc.id, function(err) {
            writeTimeline(user, doc.id, 'clone', 'system cloned');
            cb(err, {id: doc.id, err: err});
          });
        });
      });
    }
    else {
      cb(new Error('invalid url: ' + url));
    }
  };

  /**
   * create a new system by linking from local file system
   */
  var linkSystem = function(user, path_, cwd, cb) {
    var repoPath = path.resolve(cwd, path_);
    var systemJsonPath = path.join(repoPath, 'system.json');
    var doc;

    if (!fse.existsSync(systemJsonPath)) {
      return cb(new Error('`system.json` not found, please initialize the system with `nsd system create`'));
    }

    doc = fse.readFileSync(systemJsonPath);
    try {
      doc = JSON.parse(doc);
    }
    catch (e) {
      return cb(new Error('invalid system: ' + e.message));
    }

    _meta.register(user, doc.namespace, doc.name, path.basename(repoPath), repoPath, doc.id, function(err) {
      writeTimeline(user, doc.id, 'link', 'system linked');
      cb(err, {id: doc.id, err: err});
    });
  };

  var syncSystem = function(user, identifier, cb) {
    var systemId = findSystem(identifier);
    var repoPath = _meta.repoPath(systemId);
    writeTimeline(user, systemId, 'sync', 'repository synched');
    //commit(user, systemId, 'sync' + revisionId, cb);
    git.sync(repoPath, cb);
  };

  var addRemote = function(user, identifier, url, cb) {
    var systemId = findSystem(identifier);
    var repoPath = _meta.repoPath(systemId);
    writeTimeline(user, systemId, 'remote add', 'remote url added (' + url + ')');
    exports.remoteAdd(repoPath, url, function(err) {
      cb(err);
    });
  };

  var systemExists = function(namespace, name) {
    return _meta.systemExists(namespace, name);
  };

  /**
   * commit a new version of the system, the head of the commit log
   * may be ahead of the actual deployed version of the system
   */
  var commitRevision = function(user, systemId, description, sysJson, cb) {
    var repoPath = _meta.repoPath(systemId);
    fse.writeFileSync(repoPath + '/system.json', JSON.stringify(sysJson, null, 2), 'utf8');
    //writeTimeline(user, systemId, 'commit', 'system committed');
    commit(user, systemId, description, cb);
  };

  /**
   * get the head revision for a system
   */
  var getHead = function(systemId, cb) {
    listRevisions(systemId, function(err, revs) {
      getRevision(systemId, revs[0].id, cb);
    });
  };

  /**
   * get the head revision id for a system
   */
  var getHeadRevisionId = function(systemId, cb) {
    listRevisions(systemId, function(err, revs) {
      cb(err, revs[0].id);
    });
  };

  /**
   * get a revision from the history, if no version number is specified get the head
   */
  var getRevision = function(systemId, revisionId, cb) {
    var repoPath = _meta.repoPath(systemId);
    git.getFileRevision(repoPath, revisionId, 'system.json', function(err, rev) {
      if (err) { return cb(err); }
      var s;
      try {
        s = JSON.parse(rev);
      }
      catch (e) {
        return cb(new Error('invalid system definition: ' + e.message), null);
      }
      cb(err, s);
    });
  };

  /**
   * set the currently deployed revision, there will only ever be one deployed revision
   * clear the currently deployed flag and set the deployed flag against the specified revision
   */
  var markDeployedRevision = function(user, systemId, revisionId, cb) {
    var repoPath = _meta.repoPath(systemId);
    fse.writeFileSync(repoPath + '/deployed.json', '{"deployed": "' + revisionId + '"}', 'utf8');
    writeTimeline(user, systemId, 'deploy', 'system deployed to revision ' + revisionId);
    cb(null);
    //commit(user, systemId, 'system deployed to revision ' + revisionId, cb);
  };

  var markDeployedRevisionNoCommit = function(user, systemId, revisionId, cb) {
    var repoPath = _meta.repoPath(systemId);
    fse.writeFileSync(repoPath + '/deployed.json', '{"deployed": "' + revisionId + '"}', 'utf8');
    writeTimeline(user, systemId, 'deploy', 'system deployed to revision ' + revisionId);
    cb(null);
  };

  /**
   * get the currently deployed revision
   */
  var getDeployedRevisionId = function(systemId, cb) {
    var repoPath = _meta.repoPath(systemId);
    fse.readFile(repoPath + '/deployed.json', 'utf8', function(err, data) {
      var deployed = JSON.parse(data);
      cb(err, deployed.deployed);
    });
  };

  /**
   * get the currently deployed revision
   */
  var getDeployedRevision = function(systemId, cb) {
    getDeployedRevisionId(systemId, function(err, revisionId) {
      if (err) { return cb(err); }
      if (revisionId) {
        getRevision(systemId, revisionId, cb);
      }
      else {
        cb(null, null);
      }
    });
  };

  /**
   * list all of the available revisions in the system
   */
  //TODO: needs to show the deployed revision
  var listRevisions = function(systemId, cb) {
    var repoPath = _meta.repoPath(systemId);
    git.listRevisions(repoPath, function(err, revisions) {
      getDeployedRevisionId(systemId, function(err, revisionId) {
        if (revisionId) {
          var deployed = _.find(revisions, function(revision) { return revisionId === revision.id; });
          if (deployed) {
            deployed.deployed = true;
          }
        }
        cb(err, revisions);
      });
    });
  };

  /**
   * find revision id by parital or full identifier
   */
  var findRevision = function(systemId, identifier, cb) {
    var re = new RegExp('^' + identifier + '.*', ['i']);
    var revision;

    listRevisions(systemId, function(err, revisions) {
      revision = _.find(revisions, function(revision) { return re.test(revision.id); });
      if (revision) {
        cb(err, revision.id);
      }
      else {
        cb(new Error('revision not found'));
      }
    });
  };

  var sid = function(namespace, name) {
    return _meta.repoId(namespace + '_' + name);
  };

  var boot = function(cb) {
    _meta = srMeta(options);
    _meta.boot(cb);
  };

  var listSystems = function(cb) {
    return _meta.listSystems(cb);
  };

  var findSystem = function(identifier) {
    return _meta.findSystem(identifier);
  };

  var findContainer = function(systemId, identifier, cb) {
    var containerId;

    getHead(systemId, function(err, data) {
      if (err) { return cb(err); }
      if (data.containerDefinitions.length > 0) {
        _.each(data.containerDefinitions, function(cdef) {
          if (cdef.id === identifier) {
            containerId = cdef.id;
          }
          else if (cdef.id.indexOf(identifier) !== -1) {
            containerId = cdef.id;
          }
          else if (cdef.name === identifier) {
            containerId = cdef.id;
          }
        });
        cb(null, containerId);
      }
      else {
        cb(new Error('getHead returned 0 data'));
      }
    });
  };

  var addContainer = function(user, systemId, cont, cb) {
    getHead(systemId, function(err, head) {
      if (err) { return cb(err); }
      head.containerDefinitions.push(cont);
      commitRevision(user, systemId, 'added container', head, cb);
    });
  };

  var putContainer = function(user, systemId, cont, cb) {
    var foundIdx = -1;
    var idx = 0;

    getHead(systemId, function(err, head) {
      if (err) { return cb(err); }
      _.each(head.containerDefinitions, function(cdef) {
        if (cdef.id === cont.id) {
          foundIdx = idx;
        }
        ++idx;
      });
      if (foundIdx !== -1) {
        head.containerDefinitions[foundIdx] = cont;
      }
      commitRevision(user, systemId, 'updated container', head, cb);
    });
  };

  var deleteContainer = function(user, systemId, identifier, cb) {
    var foundIdx = -1;
    var idx = 0;

    findContainer(systemId, identifier, function(err, containerId) {
      if (err) { return cb(err); }
      getHead(systemId, function(err, head) {
        if (err) { return cb(err); }
        _.each(head.containerDefinitions, function(cdef) {
          if (cdef.id === containerId) {
            foundIdx = idx;
          }
          ++idx;
        });
        if (foundIdx !== -1) {
          delete head.containerDefinitions[foundIdx];
          head.containerDefinitions.splice(foundIdx, 1);
        }
        commitRevision(user, systemId, 'removed container', head, cb);
      });
    });
  };

  var repoPath = function(systemId) {
    return _meta.repoPath(systemId);
  };

  return {
    boot: boot,
    createSystem: createSystem,
    cloneSystem: cloneSystem,
    linkSystem: linkSystem,
    syncSystem: syncSystem,
    addRemote: addRemote,
    systemExists: systemExists,
    commitRevision: commitRevision,
    markDeployedRevision: markDeployedRevision,
    markDeployedRevisionNoCommit: markDeployedRevisionNoCommit,
    getDeployedRevision: getDeployedRevision,
    getDeployedRevisionId: getDeployedRevisionId,
    listRevisions: listRevisions,
    getHead: getHead,
    getHeadRevisionId: getHeadRevisionId,
    getRevision: getRevision,
    sid: sid,
    listSystems: listSystems,
    findSystem: findSystem,
    findContainer: findContainer,
    findRevision: findRevision,
    addContainer: addContainer,
    putContainer: putContainer,
    deleteContainer: deleteContainer,
    getTimeline: getTimeline,
    writeTimeline: writeTimeline,
    repoPath: repoPath
  };
};

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

'use strict';

var path = require('path');
var _ = require('lodash');
var fse = require('fs-extra');
var uuid = require('uuid');
var git = require('./gitutil');
var srMeta = require('./sysrevMeta');
var ku = require('../kutils');
var blank = {'name': '',
             'namespace': '',
             'id': '',
             'containerDefinitions': [],
             'topology': {'containers': {}}};

/**
 * maintains system commit log and history using nodegit
 * uses master branch only
 * need to be able to create a new repo on demand - for new system definition
 */
module.exports = function(options, logger) {

  var _meta;

  /**
   * ensures that system has all required files, and reads system.json
   */
  var initNscaleFiles = function(repoPath, doc) {
    fse.writeFileSync(path.join(repoPath, 'system.json'), JSON.stringify(doc, null, 2), 'utf8');
    fse.writeFileSync(path.join(repoPath, 'deployed.json'), '{"deployed": null}', 'utf8');
    fse.writeFileSync(path.join(repoPath, 'timeline.json'), '{"entries": []}', 'utf8');
    fse.writeFileSync(path.join(repoPath, '.gitignore'), 'workspace\nbuilds\n', 'utf8');
  };

  /**
   * timeline format
   * {
   *   entries: [{user: user, ts: new Date(), type: entryType, details: details},...
   * }
   */
  // TODO fix this - need to just do file append rather than read / write
  var writeTimeline = function(user, systemId, entryType, details) {
    var repoPath = _meta.repoPath(systemId);
    var timeline;
    var entry;

    timeline = fse.readFileSync(repoPath + '/timeline.json', 'utf8');
    timeline = JSON.parse(timeline);
    entry = {user: user, ts: new Date(), type: entryType, details: details};
    timeline.entries.push(entry);
    fse.writeFileSync(repoPath + '/timeline.json', JSON.stringify(timeline), 'utf8');
  };

  // TODO: fix this - don't want huge blocks of JSON need to partition up
  var getTimeline = function(systemId, cb) {
    var repoPath = _meta.repoPath(systemId);
    var timeline;

    timeline = fse.readFileSync(repoPath + '/timeline.json', 'utf8');
    timeline = JSON.parse(timeline);
    if (timeline.entries) {timeline.entries.reverse();}
    cb(null, timeline);
  };

  /**
   * make a commit to local git repository
   * TODO: implement seperate push functionality
   * TODO: replace with git hub id
   */
  var commit = function(user, systemId, message, cb) {
    logger.info('commiting revision: ' + systemId + ', ' + message);
    var repoPath = _meta.repoPath(systemId);
    git.commit(repoPath, ['system.json', 'timeline.json', 'deployed.json'], message, user.name, user.email, cb);
  };

  /**
   * create a new system repository
   */
  var createSystem = function(user, namespace, name, cwd, cb) {
    //var repoName = namespace + '_' + name;
    var repoName = name;
    var doc = _.extend({}, blank);
    var repoPath = path.join(cwd, repoName);

    doc.name = name;
    doc.namespace = namespace;
    doc.id = uuid.v4();

    if (!fse.existsSync(path.join(repoPath, 'system.json'))) {
      fse.mkdirpSync(repoPath);
      initNscaleFiles(repoPath, doc);
      git.createRepository(repoPath, ['system.json', 'deployed.json', 'timeline.json'], user.name, user.email, function(err) {
        if (err) { return cb(err); }
        _meta.register(user, namespace, name, repoName, cwd + '/' + repoName, doc.id, function(err) {
          writeTimeline(user, doc.id, 'create', 'system created');
          cb(err, {id: doc.id, err: err});
        });
      });
    }
    else {
      cb(null, { id: _meta.repoId(repoName), err: null});
    }
  };

  /**
   * create a new system by pulling from an existing repository
   *
   * var test1 = 'git@github.com:pelger/mlshack.git';
   * var test2 = 'https://github.com/pelger/mlshack.git';
   */
  var cloneSystem = function(user, url, cwd, cb) {
    var repoName;
    var repoPath;
    var doc;

    if (ku.checkGitUrl(url)) {
      repoName = ku.parseGitUrl(url).repo;
      repoPath = path.join(cwd, repoName);
      git.clone(url, repoPath, function(err) {
        if (err) { return cb(err); }
        if (fse.existsSync(path.join(repoPath, 'system.json'))) {
          doc = fse.readFileSync(path.join(repoPath, 'system.json'), 'utf8');
          try {
            doc = JSON.parse(doc);
          }
          catch (e) {
            return cb(new Error('invalid system: ' + e.message));
          }
        }
        else {
          doc = _.extend({}, blank);
          doc.name = repoName;
          doc.namespace = repoName;
          doc.id = uuid.v4();
          doc.remoteUrl = url;
          initNscaleFiles(repoPath, doc);
        }
        git.initClonedRepo(repoPath, ['system.json', 'deployed.json', 'timeline.json'], user.name, user.email, function(err) {
          if (err) { return cb(err); }
          // namespce and name parameters...
          _meta.register(user, doc.namespace, doc.name, repoName, repoPath, doc.id, function(err) {
            writeTimeline(user, doc.id, 'clone', 'system cloned');
            cb(err, {id: doc.id, err: err});
          });
        });
      });
    }
    else {
      cb(new Error('invalid url: ' + url));
    }
  };

  /**
   * create a new system by linking from local file system
   */
  var linkSystem = function(user, path_, cwd, cb) {
    var repoPath = path.resolve(cwd, path_);
    var systemJsonPath = path.join(repoPath, 'system.json');
    var doc;

    if (!fse.existsSync(systemJsonPath)) {
      return cb(new Error('`system.json` not found, please initialize the system with `nsd system create`'));
    }

    doc = fse.readFileSync(systemJsonPath);
    try {
      doc = JSON.parse(doc);
    }
    catch (e) {
      return cb(new Error('invalid system: ' + e.message));
    }

    _meta.register(user, doc.namespace, doc.name, path.basename(repoPath), repoPath, doc.id, function(err) {
      writeTimeline(user, doc.id, 'link', 'system linked');
      cb(err, {id: doc.id, err: err});
    });
  };

  var syncSystem = function(user, identifier, cb) {
    var systemId = findSystem(identifier);
    var repoPath = _meta.repoPath(systemId);
    writeTimeline(user, systemId, 'sync', 'repository synched');
    //commit(user, systemId, 'sync' + revisionId, cb);
    git.sync(repoPath, cb);
  };

  var addRemote = function(user, identifier, url, cb) {
    var systemId = findSystem(identifier);
    var repoPath = _meta.repoPath(systemId);
    writeTimeline(user, systemId, 'remote add', 'remote url added (' + url + ')');
    exports.remoteAdd(repoPath, url, function(err) {
      cb(err);
    });
  };

  var systemExists = function(namespace, name) {
    return _meta.systemExists(namespace, name);
  };

  /**
   * commit a new version of the system, the head of the commit log
   * may be ahead of the actual deployed version of the system
   */
  var commitRevision = function(user, systemId, description, sysJson, cb) {
    var repoPath = _meta.repoPath(systemId);
    delete sysJson.repoPath;
    fse.writeFileSync(repoPath + '/system.json', JSON.stringify(sysJson, null, 2), 'utf8');
    //writeTimeline(user, systemId, 'commit', 'system committed');
    commit(user, systemId, description, cb);
  };

  /**
   * get the head revision for a system
   */
  var getHead = function(systemId, cb) {
    listRevisions(systemId, function(err, revs) {
      getRevision(systemId, revs[0].id, cb);
    });
  };

  /**
   * get the head revision id for a system
   */
  var getHeadRevisionId = function(systemId, cb) {
    listRevisions(systemId, function(err, revs) {
      cb(err, revs[0].id);
    });
  };

  /**
   * get a revision from the history, if no version number is specified get the head
   */
  var getRevision = function(systemId, revisionId, cb) {
    var repoPath = _meta.repoPath(systemId);
    git.getFileRevision(repoPath, revisionId, 'system.json', function(err, rev) {
      if (err) { return cb(err); }
      var s;
      try {
        s = JSON.parse(rev);
      }
      catch (e) {
        return cb(new Error('invalid system definition: ' + e.message), null);
      }
      cb(err, s);
    });
  };

  /**
   * set the currently deployed revision, there will only ever be one deployed revision
   * clear the currently deployed flag and set the deployed flag against the specified revision
   */
  var markDeployedRevision = function(user, systemId, revisionId, cb) {
    var repoPath = _meta.repoPath(systemId);
    fse.writeFileSync(repoPath + '/deployed.json', '{"deployed": "' + revisionId + '"}', 'utf8');
    writeTimeline(user, systemId, 'deploy', 'system deployed to revision ' + revisionId);
    cb(null);
    //commit(user, systemId, 'system deployed to revision ' + revisionId, cb);
  };

  var markDeployedRevisionNoCommit = function(user, systemId, revisionId, cb) {
    var repoPath = _meta.repoPath(systemId);
    fse.writeFileSync(repoPath + '/deployed.json', '{"deployed": "' + revisionId + '"}', 'utf8');
    writeTimeline(user, systemId, 'deploy', 'system deployed to revision ' + revisionId);
    cb(null);
  };

  /**
   * get the currently deployed revision
   */
  var getDeployedRevisionId = function(systemId, cb) {
    var repoPath = _meta.repoPath(systemId);
    fse.readFile(repoPath + '/deployed.json', 'utf8', function(err, data) {
      var deployed = JSON.parse(data);
      cb(err, deployed.deployed);
    });
  };

  /**
   * get the currently deployed revision
   */
  var getDeployedRevision = function(systemId, cb) {
    getDeployedRevisionId(systemId, function(err, revisionId) {
      if (err) { return cb(err); }
      if (revisionId) {
        getRevision(systemId, revisionId, cb);
      }
      else {
        cb(null, null);
      }
    });
  };

  /**
   * list all of the available revisions in the system
   */
  //TODO: needs to show the deployed revision
  var listRevisions = function(systemId, cb) {
    var repoPath = _meta.repoPath(systemId);
    git.listRevisions(repoPath, function(err, revisions) {
      getDeployedRevisionId(systemId, function(err, revisionId) {
        if (revisionId) {
          var deployed = _.find(revisions, function(revision) { return revisionId === revision.id; });
          if (deployed) {
            deployed.deployed = true;
          }
        }
        cb(err, revisions);
      });
    });
  };

  /**
   * find revision id by parital or full identifier
   */
  var findRevision = function(systemId, identifier, cb) {
    var re = new RegExp('^' + identifier + '.*', ['i']);
    var revision;

    listRevisions(systemId, function(err, revisions) {
      revision = _.find(revisions, function(revision) { return re.test(revision.id); });
      if (revision) {
        cb(err, revision.id);
      }
      else {
        cb(new Error('revision not found'));
      }
    });
  };

  var sid = function(namespace, name) {
    return _meta.repoId(namespace + '_' + name);
  };

  var boot = function(cb) {
    _meta = srMeta(options);
    _meta.boot(cb);
  };

  var listSystems = function(cb) {
    return _meta.listSystems(cb);
  };

  var findSystem = function(identifier) {
    return _meta.findSystem(identifier);
  };

  var findContainer = function(systemId, identifier, cb) {
    var containerId;

    getHead(systemId, function(err, data) {
      if (err) { return cb(err); }
      if (data.containerDefinitions.length > 0) {
        _.each(data.containerDefinitions, function(cdef) {
          if (cdef.id === identifier) {
            containerId = cdef.id;
          }
          else if (cdef.id.indexOf(identifier) !== -1) {
            containerId = cdef.id;
          }
          else if (cdef.name === identifier) {
            containerId = cdef.id;
          }
        });
        cb(null, containerId);
      }
      else {
        cb(new Error('getHead returned 0 data'));
      }
    });
  };

  var addContainer = function(user, systemId, cont, cb) {
    getHead(systemId, function(err, head) {
      if (err) { return cb(err); }
      head.containerDefinitions.push(cont);
      commitRevision(user, systemId, 'added container', head, cb);
    });
  };

  var putContainer = function(user, systemId, cont, cb) {
    var foundIdx = -1;
    var idx = 0;

    getHead(systemId, function(err, head) {
      if (err) { return cb(err); }
      _.each(head.containerDefinitions, function(cdef) {
        if (cdef.id === cont.id) {
          foundIdx = idx;
        }
        ++idx;
      });
      if (foundIdx !== -1) {
        head.containerDefinitions[foundIdx] = cont;
      }
      commitRevision(user, systemId, 'updated container', head, cb);
    });
  };

  var deleteContainer = function(user, systemId, identifier, cb) {
    var foundIdx = -1;
    var idx = 0;

    findContainer(systemId, identifier, function(err, containerId) {
      if (err) { return cb(err); }
      getHead(systemId, function(err, head) {
        if (err) { return cb(err); }
        _.each(head.containerDefinitions, function(cdef) {
          if (cdef.id === containerId) {
            foundIdx = idx;
          }
          ++idx;
        });
        if (foundIdx !== -1) {
          delete head.containerDefinitions[foundIdx];
          head.containerDefinitions.splice(foundIdx, 1);
        }
        commitRevision(user, systemId, 'removed container', head, cb);
      });
    });
  };

  var repoPath = function(systemId) {
    return _meta.repoPath(systemId);
  };

  return {
    boot: boot,
    createSystem: createSystem,
    cloneSystem: cloneSystem,
    linkSystem: linkSystem,
    syncSystem: syncSystem,
    addRemote: addRemote,
    systemExists: systemExists,
    commitRevision: commitRevision,
    markDeployedRevision: markDeployedRevision,
    markDeployedRevisionNoCommit: markDeployedRevisionNoCommit,
    getDeployedRevision: getDeployedRevision,
    getDeployedRevisionId: getDeployedRevisionId,
    listRevisions: listRevisions,
    getHead: getHead,
    getHeadRevisionId: getHeadRevisionId,
    getRevision: getRevision,
    sid: sid,
    listSystems: listSystems,
    findSystem: findSystem,
    findContainer: findContainer,
    findRevision: findRevision,
    addContainer: addContainer,
    putContainer: putContainer,
    deleteContainer: deleteContainer,
    getTimeline: getTimeline,
    writeTimeline: writeTimeline,
    repoPath: repoPath
  };
};

<|endoftext|>


<commit_before>/*
 * Copyright 2009-2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE.txt or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

define(function(require, exports, module) {

var dom = require('gcli/util').dom;
var canon = require('gcli/canon');
var domtemplate = require("gcli/ui/domtemplate");

var examiner = require("test/examiner");

var testCss = require("text!test/ui/test.css");
var testHtml = require('text!test/ui/test.html');

var template;

/**
 * Registration and de-registration.
 */
exports.setup = function() {
  canon.addCommand(testCommandSpec);
};

exports.shutdown = function() {
  canon.removeCommand(testCommandSpec);
};

/**
 * The 'test' command
 */
var testCommandSpec = {
  name: 'test',
  description: 'Runs the GCLI Unit Tests',
  params: [],
  exec: function(env, context) {
    if (!template) {
      dom.importCss(testCss, context.document);
      template = dom.createElement(context.document, 'div');
      dom.setInnerHtml(template, testHtml);
    }

    var promise = context.createPromise();
    var options = {};

    examiner.runAsync(options, function() {
      var newNode = template.cloneNode(true);
      domtemplate.template(newNode, examiner.toRemote(), {
        allowEval: true,
        stack: 'test.html'
      });
      promise.resolve(newNode);
    });
    return promise;
  }
};

});
<commit_msg>Bug 709223 (resource): Correctly setup test environment for command line test case<commit_after>/*
 * Copyright 2009-2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE.txt or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

define(function(require, exports, module) {

var dom = require('gcli/util').dom;
var canon = require('gcli/canon');
var domtemplate = require("gcli/ui/domtemplate");

var examiner = require("test/examiner");

var testCss = require("text!test/ui/test.css");
var testHtml = require('text!test/ui/test.html');

var template;

/**
 * Registration and de-registration.
 */
exports.setup = function() {
  canon.addCommand(testCommandSpec);
};

exports.shutdown = function() {
  canon.removeCommand(testCommandSpec);
};

/**
 * The 'test' command
 */
var testCommandSpec = {
  name: 'test',
  description: 'Runs the GCLI Unit Tests',
  params: [],
  exec: function(env, context) {
    if (!template) {
      dom.importCss(testCss, context.document);
      template = dom.createElement(context.document, 'div');
      dom.setInnerHtml(template, testHtml);
    }

    var promise = context.createPromise();
    var options = { window: window };

    examiner.runAsync(options, function() {
      var newNode = template.cloneNode(true);
      domtemplate.template(newNode, examiner.toRemote(), {
        allowEval: true,
        stack: 'test.html'
      });
      promise.resolve(newNode);
    });
    return promise;
  }
};

});
<|endoftext|>