<commit_before>(function(angular){
    'use strict';

    var module = angular.module('edit_class.controllers', []);

    // Service to share data across the controllers
    module.factory('classe_list', function() {
        return {
            classe : []
        };
    });

    module.controller('ClassController', ['$scope', '$window', 'Class', 'StudentSearch',
        function($scope, $window, Class, StudentSearch) {

            $scope.errors = {};
            var httpErrors = {
                '400': 'Os campos não foram preenchidos corretamente.',
                '403': 'Você não tem permissão para ver conteúdo nesta página.',
                '404': 'Esta classe não existe!',
                '405': 'Alguma coisa parece ter dado errado!',
            };

            $scope.class_id = parseInt($window.class_id, 10);
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.classe = Class.get({id: $scope.class_id}, function(classe) {

                // if($scope.classe.assistant) {
                //     angular.forEach($scope.classe.course.professors, function(value, key) {
                //         if(value.id == $scope.classe.assistant) {
                //             $scope.classe.assistant = value;
                //         }
                //     });
                // }

                console.log(classe);
                document.title = 'Turma: {0}'.format(classe.name);
            });

            $scope.getUsers = function(val) {
                return new StudentSearch(val, course_id);
            };

            $scope.remove_item = function(index){
                $scope.classe.students.splice(index, 1);
                $scope.classe.students_management.splice(index, 1);
                $scope.save();
            };

            $scope.on_select_student = function(model) {
                $scope.classe.students.unshift(model);
                $scope.classe.students_management.unshift(model.id);
                $scope.asyncSelected = '';
                $scope.save();
            };

            $scope.save = function(){

                if($scope.classe.assistant) {
                    $scope.classe.assistant_management = $scope.classe.assistant.id;
                }

                $scope.classe.$update()
                    .then(function(){
                        $scope.alert.success('Alterações salvas com sucesso.');

                        // remove pop-up that confirm if user go without save changes
                        window.onbeforeunload = function(){};

                        })['catch'](function(resp){
                            $scope.alert.error(httpErrors[resp.status.toString()]);
                        });
            }

        }
    ]);
})(angular);
<commit_msg>removing debug code<commit_after>(function(angular){
    'use strict';

    var module = angular.module('edit_class.controllers', []);

    // Service to share data across the controllers
    module.factory('classe_list', function() {
        return {
            classe : []
        };
    });

    module.controller('ClassController', ['$scope', '$window', 'Class', 'StudentSearch',
        function($scope, $window, Class, StudentSearch) {

            $scope.errors = {};
            var httpErrors = {
                '400': 'Os campos não foram preenchidos corretamente.',
                '403': 'Você não tem permissão para ver conteúdo nesta página.',
                '404': 'Esta classe não existe!',
                '405': 'Alguma coisa parece ter dado errado!',
            };

            $scope.class_id = parseInt($window.class_id, 10);
            $scope.course_id = parseInt($window.course_id, 10);
            $scope.classe = Class.get({id: $scope.class_id}, function(classe) {
                document.title = 'Turma: {0}'.format(classe.name);
            });

            $scope.getUsers = function(val) {
                return new StudentSearch(val, course_id);
            };

            $scope.remove_item = function(index){
                $scope.classe.students.splice(index, 1);
                $scope.classe.students_management.splice(index, 1);
                $scope.save();
            };

            $scope.on_select_student = function(model) {
                $scope.classe.students.unshift(model);
                $scope.classe.students_management.unshift(model.id);
                $scope.asyncSelected = '';
                $scope.save();
            };

            $scope.save = function(){

                if($scope.classe.assistant) {
                    $scope.classe.assistant_management = $scope.classe.assistant.id;
                }

                $scope.classe.$update()
                    .then(function(){
                        $scope.alert.success('Alterações salvas com sucesso.');

                        // remove pop-up that confirm if user go without save changes
                        window.onbeforeunload = function(){};

                        })['catch'](function(resp){
                            $scope.alert.error(httpErrors[resp.status.toString()]);
                        });
            }

        }
    ]);
})(angular);
<|endoftext|>


<commit_before>import _ from 'lodash';
import React from 'react';

export default class AnimatedStack extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      isInTransition: false,
      layersStyles: this.getDefaultStyles(props.activeLayerIndex)
    }
  }

  getDefaultStyles(currentIndex, nextIndex) {
    const {children} = this.props;
    const activeIndexes = [currentIndex, nextIndex].filter(_.isString)

    return children.reduce((acc, child) => {
      const {index} = child.props;

      acc[index] = { position: 'absolute' };

      const active = _.includes(activeIndexes, index);

      // move inactive layers in the background
      if (!active) {
        acc[index]['zIndex'] = '-1000'
      }

      return acc;
    }, {})
  }

  getAnimationObject(currentIndex, nextIndex) {
    let isReverse = false;

    const animation = _.find(this.props.animations, ({from, to}) => {
      const fromExist = _.isString(from);
      const toExist = _.isString(to);

      const fromMatchForward = from === currentIndex;
      const toMatchForward = to === nextIndex;

      const isForward =
        (fromExist && fromMatchForward && toExist && toMatchForward) ||
        (fromExist && fromMatchForward && !toExist) ||
        (!fromExist && toExist && toMatchForward);

      if (isForward) {
        return true;
      }

      const fromMatchBackward = from === nextIndex;
      const toMatchBackward = to === currentIndex;

      const isBackward =
        (fromExist && fromMatchBackward && toExist && toMatchBackward) ||
        (fromExist && fromMatchBackward && !toExist) ||
        (!fromExist && toExist && toMatchBackward);

      if (isBackward) {
        isReverse = true;
        return true;
      }
    });

    if (!animation) {
      return null
    }

    if (!isReverse) {
      return animation.use();
    }

    if (animation.reverse) {
      return animation.reverse();
    }

    const animationObject = animation.use();

    exchangeVaules(animationObject, 'currentLayer', 'nextLayer');
    _.each(animationObject, (value, key) => {
      value && exchangeVaules(value, 'startStyle', 'endStyle');
    });

    return animationObject;
  }

  // layer: 'currentlayer' | 'nextLayer'
  // type: 'startStyle' | 'endStyle'
  getStyleForLayer(animationObject, layer, type, index) {
    const style = _.get(animationObject, [layer, type]);

    if (!style) {
      return {};
    }

    if (type === 'endStyle') {
      style.transition = animationObject[layer].transition;
    } else if (this.state.isInTransition) {
      style.transition = _.get(this.state.layersStyles, [index, 'transition'])
    }

    return style;
  }

  // type: 'startStyle' | 'endStyle'
  layersStylesForAnimation(defaultStyles, currentIndex, nextIndex, animationObject, type) {
    const layersStyles = _.cloneDeep(defaultStyles);

    _.extend(
      layersStyles[currentIndex],
      this.getStyleForLayer(animationObject, 'currentLayer', type, currentIndex)
    );

    _.extend(
      layersStyles[nextIndex],
      this.getStyleForLayer(animationObject, 'nextLayer', type, nextIndex)
    );

    return layersStyles;
  }

  componentWillReceiveProps(nextProps) {
    const currentIndex = this.props.activeLayerIndex;
    const nextIndex = nextProps.activeLayerIndex;

    if (currentIndex !== nextIndex) {
      const animationObject = this.getAnimationObject(currentIndex, nextIndex);

      if (!animationObject) {
        this.setState({
          isInTransition: false,
          layersStyles: this.getDefaultStyles(nextIndex)
        });
        return
      }

      const defaultStyles = this.getDefaultStyles(currentIndex, nextIndex);

      const layersStylesStart = this.layersStylesForAnimation(
        defaultStyles, currentIndex, nextIndex, animationObject, 'startStyle'
      );
      this.setState({layersStyles: layersStylesStart});

      // NOTE: maybe we should use animation instead of transition
      // since here we need timeout for brower to konw the change of style
      setTimeout(() => {
        const layersStylesEnd = this.layersStylesForAnimation(
          defaultStyles, currentIndex, nextIndex, animationObject, 'endStyle'
        );
        this.setState({
          isInTransition: true,
          layersStyles: layersStylesEnd
        });
      }, 50);
    }
  }

  handleTransitionEnd(e) {
    this.setState({
      isInTransition: false,
      layersStyles: this.getDefaultStyles(this.props.activeLayerIndex)
    });
  }

  render () {
    const {children, animations, activeLayerIndex, ...other} = this.props;
    const layers = children.map((child) => {
      const {index} = child.props;

      return (
        <div
          key={index}
          style={this.state.layersStyles[index]}
          onTransitionEnd={(e) => this.handleTransitionEnd(e)}>
          {child}
        </div>
      );
    })

    return (
      <div {...other}>
        {layers}
      </div>
    )
  }
}

function exchangeVaules(obj, first, second) {
  const temp = obj[first];
  obj[first] = obj[second];
  obj[second] = temp;
  return obj;
}
<commit_msg>feat: use opacity to boost performance<commit_after>import _ from 'lodash';
import React from 'react';

export default class AnimatedStack extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      isInTransition: false,
      layersStyles: this.getDefaultStyles(props.activeLayerIndex)
    }
  }

  getDefaultStyles(currentIndex, nextIndex) {
    const {children} = this.props;
    const activeIndexes = [currentIndex, nextIndex].filter(_.isString)

    return children.reduce((acc, child) => {
      const {index} = child.props;

      acc[index] = { position: 'absolute' };

      const active = _.includes(activeIndexes, index);

      // move inactive layers in the background
      if (!active) {
        acc[index]['opacity'] = '0'
        acc[index]['zIndex'] = '-1000'
      }

      return acc;
    }, {})
  }

  getAnimationObject(currentIndex, nextIndex) {
    let isReverse = false;

    const animation = _.find(this.props.animations, ({from, to}) => {
      const fromExist = _.isString(from);
      const toExist = _.isString(to);

      const fromMatchForward = from === currentIndex;
      const toMatchForward = to === nextIndex;

      const isForward =
        (fromExist && fromMatchForward && toExist && toMatchForward) ||
        (fromExist && fromMatchForward && !toExist) ||
        (!fromExist && toExist && toMatchForward);

      if (isForward) {
        return true;
      }

      const fromMatchBackward = from === nextIndex;
      const toMatchBackward = to === currentIndex;

      const isBackward =
        (fromExist && fromMatchBackward && toExist && toMatchBackward) ||
        (fromExist && fromMatchBackward && !toExist) ||
        (!fromExist && toExist && toMatchBackward);

      if (isBackward) {
        isReverse = true;
        return true;
      }
    });

    if (!animation) {
      return null
    }

    if (!isReverse) {
      return animation.use();
    }

    if (animation.reverse) {
      return animation.reverse();
    }

    const animationObject = animation.use();

    exchangeVaules(animationObject, 'currentLayer', 'nextLayer');
    _.each(animationObject, (value, key) => {
      value && exchangeVaules(value, 'startStyle', 'endStyle');
    });

    return animationObject;
  }

  // layer: 'currentlayer' | 'nextLayer'
  // type: 'startStyle' | 'endStyle'
  getStyleForLayer(animationObject, layer, type, index) {
    const style = _.get(animationObject, [layer, type]);

    if (!style) {
      return {};
    }

    if (type === 'endStyle') {
      style.transition = animationObject[layer].transition;
    } else if (this.state.isInTransition) {
      style.transition = _.get(this.state.layersStyles, [index, 'transition'])
    }

    return style;
  }

  // type: 'startStyle' | 'endStyle'
  layersStylesForAnimation(defaultStyles, currentIndex, nextIndex, animationObject, type) {
    const layersStyles = _.cloneDeep(defaultStyles);

    _.extend(
      layersStyles[currentIndex],
      this.getStyleForLayer(animationObject, 'currentLayer', type, currentIndex)
    );

    _.extend(
      layersStyles[nextIndex],
      this.getStyleForLayer(animationObject, 'nextLayer', type, nextIndex)
    );

    return layersStyles;
  }

  componentWillReceiveProps(nextProps) {
    const currentIndex = this.props.activeLayerIndex;
    const nextIndex = nextProps.activeLayerIndex;

    if (currentIndex !== nextIndex) {
      const animationObject = this.getAnimationObject(currentIndex, nextIndex);

      if (!animationObject) {
        this.setState({
          isInTransition: false,
          layersStyles: this.getDefaultStyles(nextIndex)
        });
        return
      }

      const defaultStyles = this.getDefaultStyles(currentIndex, nextIndex);

      const layersStylesStart = this.layersStylesForAnimation(
        defaultStyles, currentIndex, nextIndex, animationObject, 'startStyle'
      );
      this.setState({layersStyles: layersStylesStart});

      // NOTE: maybe we should use animation instead of transition
      // since here we need timeout for brower to konw the change of style
      setTimeout(() => {
        const layersStylesEnd = this.layersStylesForAnimation(
          defaultStyles, currentIndex, nextIndex, animationObject, 'endStyle'
        );
        this.setState({
          isInTransition: true,
          layersStyles: layersStylesEnd
        });
      }, 50);
    }
  }

  handleTransitionEnd(e) {
    this.setState({
      isInTransition: false,
      layersStyles: this.getDefaultStyles(this.props.activeLayerIndex)
    });
  }

  render () {
    const {children, animations, activeLayerIndex, ...other} = this.props;
    const layers = children.map((child) => {
      const {index} = child.props;

      return (
        <div
          key={index}
          style={this.state.layersStyles[index]}
          onTransitionEnd={(e) => this.handleTransitionEnd(e)}>
          {child}
        </div>
      );
    })

    return (
      <div {...other}>
        {layers}
      </div>
    )
  }
}

function exchangeVaules(obj, first, second) {
  const temp = obj[first];
  obj[first] = obj[second];
  obj[second] = temp;
  return obj;
}
<|endoftext|>


<commit_before>/**
 * Created by elad.benedict on 8/26/2015.
 */

var Q = require('q');
var _ = require('underscore');
var kalturaVO = require('./kaltura-client-lib/KalturaVO');
var kalturaClient = require('./kaltura-client-lib/KalturaClient');
var kalturaClientBase = require('./kaltura-client-lib/KalturaClientBase');
var kalturaTypes = require('./kaltura-client-lib/KalturaTypes');
var config = require('./../common/Configuration');
var moduleLogger = require('./logger/logger')(module);

var BackendClient = (function(){

    function createClientConfig() {
        var conf = new kalturaClientBase.KalturaConfiguration(partnerId);
        conf.serviceUrl = config.get('backendClient').serviceUrl;
        return conf;
    }

    function convertToMs(minutes) {
        return minutes * 60 * 1000;
    }

    var lastSessionTime = null;
    var adminSecret = config.get('backendClient').adminSecret;
    var partnerId = config.get('backendClient').partnerId;
    var mediaServerHostname = config.get('mediaServer').hostname;
    var applicationName = config.get('mediaServer').applicationName;
    var client = null;
    var clientConfig = createClientConfig();
    var sessionDuration = convertToMs(config.get('backendClient').ksSessionRefreshIntervalMinutes);
    var BackendClient = {};
    var mediaServerIndexPromise = null;

    function printAPIResponse(logger, result, headers) {
        logger.info("API call headers: %j", headers);
        if(result)
            logger.info("API call result: %j", result);
    }

    function createSession() {
        var deferred = Q.defer();
        var now = new Date();
        //create session
        if (!lastSessionTime || (now - lastSessionTime) > sessionDuration) {
            moduleLogger.debug("Request for createSession started");
            client = new kalturaClient.KalturaClient(clientConfig);
            client.session.start(function(results, err, headers) {
                var endTime  = new Date();
                var operationTime = endTime - now;
                moduleLogger.debug("Request for createSession took %s", operationTime);
                if (err) {
                    moduleLogger.error("Failed to create session: %j", err);
                    printAPIResponse(moduleLogger, results, headers);
                    deferred.reject(err);
                }
                if (results) {
                    lastSessionTime = now;
                    moduleLogger.info("session created successfully %j", results);
                    client.setSessionId(results);
                    deferred.resolve();
                }
            }, adminSecret, null, kalturaTypes.KalturaSessionType.ADMIN, partnerId, null, null);
        }
        else {
            deferred.resolve();
        }

        return deferred.promise;
    }

    function getMediaServerIndexPromise() {
        if (mediaServerIndexPromise) {
            return mediaServerIndexPromise;
        }

        var deferred = Q.defer();

        //get serverNode id by mediaServerHostName
        var serverNodeFilter = new kalturaVO.KalturaWowzaMediaServerNodeFilter();
        serverNodeFilter.hostNameLike = mediaServerHostname;

        client.serverNode.listAction(function(results,err,headers) {
            if (err) {
                moduleLogger.error("Failed to retrieve serverNodeIndex for host %s with error %s", mediaServerHostname, err);
                printAPIResponse(moduleLogger, results, headers);
                deferred.reject(err);
            }
            if (results && results.objects[0] && results.objects[0].objectType !== 'KalturaAPIException') {
                var serverNode = results.objects[0];
                moduleLogger.info("successfully retrieve serverNodeId for host name %s id %s", mediaServerHostname, serverNode.id);
                deferred.resolve(serverNode.id);
            }
        }, serverNodeFilter);

        mediaServerIndexPromise=deferred.promise;

        return mediaServerIndexPromise;
    }

    function convertKalturaEntry(item){
        var res = {
          "entryId" : item.id,
          "flavorParamsIds" : item.flavorParamsIds
            // TODO: Retreive ServerIndex! -> Gad
        };
        if (item.dvrStatus === kalturaTypes.KalturaDVRStatus.ENABLED) {

            if (item.dvrWindow) {
                var entryDVRWindow = item.dvrWindow * 60;     //   assuming dvrWindow from backend is in minutes!
                res.dvrWindow = Math.max(config.get("minimalDvrWindow"), entryDVRWindow);

            }
            else {
                res.dvrWindow = config.get("defaultDvrWindow");
            }

            res.maxChunkCount = config.get("dvrMaxChunkCount");
        }
        else {
            res.maxChunkCount = config.get("liveMaxChunkCount");
        }
        return res;
    }

    function getLiveEntries() {
        var deferred = Q.defer();
        var filter = new kalturaVO.KalturaLiveStreamEntryFilter();
        filter.isLive = kalturaTypes.KalturaNullableBoolean.TRUE_VALUE;
        filter.hasMediaServerHostname = mediaServerHostname;
        var pager = {
            pageSize : 300,
            pageIndex : 1
        };
        var startTime = new Date();
        moduleLogger.debug("Request for liveStream.listAction started");
        client.liveStream.listAction(function(results, err, headers) {
            var endTime = new Date();
            var operationTime = endTime - startTime;
            moduleLogger.debug("Request for liveStream.listAction took %s", operationTime);
            if (results) {
                var objs = _.map(results.objects, convertKalturaEntry);
                moduleLogger.debug("Got live entries: %j", objs);
                deferred.resolve(objs);
            }
            else {
                printAPIResponse(moduleLogger, results, headers);
                moduleLogger.error("Failed to get live entries: %s", err);
                deferred.reject(new Error("Failed to retrieve live entries from server"));
            }
        }, filter, pager);

        return deferred.promise;
    }

    function getEntryInfo(entryId, serverNodeId) {

        var deferred = Q.defer();

        //get live stream entry by Entry ID
        var startTime = new Date();
        client.liveStream.get(function(result, err, headers) {
            var endTime = new Date();
            var operationTime = endTime - startTime;
            moduleLogger.info("Got server node info for entry %s (took %d)", entryId, operationTime);
            printAPIResponse(moduleLogger, result, headers);

            if (result.objectType !== "KalturaAPIException") {  //Use to indicate success operation
                var liveEntry = convertKalturaEntry(result);

                if(result.primaryServerNodeId === serverNodeId)
                    liveEntry.serverType = kalturaTypes.KalturaEntryServerNodeType.LIVE_PRIMARY;
                else
                    liveEntry.serverType = kalturaTypes.KalturaEntryServerNodeType.LIVE_BACKUP;
                deferred.resolve(liveEntry);
            }
            else {
                moduleLogger.error("Failed to retrieve live stream entry info for from server: %s", result[0].message);
                deferred.reject(new Error("%s: %s", result.objectType, result.code));
            }
        }, entryId);

        return deferred.promise;
    }

    function registerEntryInDatabase(entryId, serverIndex, state, event, logger) {
        var deferred = Q.defer();
        logger.debug("Request for register media server started");
        client.liveStream.registerMediaServer(function(result, err, headers) {
            if (result.objectType === "KalturaLiveStreamEntry") {  //Use to indicate success operation
                logger.info("Register media server for entry finished successfully - '%s'", event.toUpperCase());
                deferred.resolve(result);   //check which object, if any, need to pass.
            }
            else {
                printAPIResponse(logger, result, headers);
                logger.error("Failed to register media server - '%s' - for entry. Error: %s", event.toUpperCase(), result.message);
                deferred.reject(new Error(result.objectType + ": " + result.code));
            }
        }, entryId, mediaServerHostname, serverIndex, applicationName , state);
        return deferred.promise;
    }

    function unregisterEntryInDatabase(entryId, serverIndex, logger) {
        var deferred = Q.defer();
        logger.debug("Request for unregister media server started");
        client.liveStream.unregisterMediaServer(function(result, err, headers) {
            if (result.objectType === "KalturaLiveStreamEntry") {  //Use to indicate success operation
                logger.info("Unregister media server for entry finished successfully");
                deferred.resolve(result);   //check which object, if any, need to pass.
            }
            else {
                printAPIResponse(logger, result, headers);
                logger.error("Failed to unregister media from server: %s", result.message);
                deferred.reject(new Error("%s: %s", result.objectType, result.code));
            }
        }, entryId, mediaServerHostname, serverIndex, applicationName);
        return deferred.promise;
    }

    BackendClient.getLiveEntriesForMediaServer = function() {
       return createSession()
           .then(function() {
                return getLiveEntries();
            });
    };

    BackendClient.getEntries = function(entryId) {
        return createSession()
            .then(function () {
                return getMediaServerIndexPromise().then(function(index) {
                    return getEntryInfo(entryId, index);
                });
            });
    };

    BackendClient.registerEntryInDatabase = function(entryObject, state, event, logger) {
        logger.info("Calling registerMediaServer, updating entry in database");
        return createSession()
            .then(function() {
                // TODO: Change hard coded 1 value to serverIndex parameter -> Gad
                return registerEntryInDatabase(entryObject.entryId, entryObject.serverType, state, event, logger);
            });
    };

    BackendClient.unregisterEntryInDatabase = function(entryId, logger) {
        logger.debug("Calling unregisterMediaServer, and delete entry from database");
        return createSession()
            .then(function() {
                return unregisterEntryInDatabase(entryId, logger);
            });

    };

    return BackendClient;
})();

module.exports = BackendClient;
<commit_msg>Minor changes<commit_after>/**
 * Created by elad.benedict on 8/26/2015.
 */

var Q = require('q');
var _ = require('underscore');
var kalturaVO = require('./kaltura-client-lib/KalturaVO');
var kalturaClient = require('./kaltura-client-lib/KalturaClient');
var kalturaClientBase = require('./kaltura-client-lib/KalturaClientBase');
var kalturaTypes = require('./kaltura-client-lib/KalturaTypes');
var config = require('./../common/Configuration');
var moduleLogger = require('./logger/logger')(module);

var BackendClient = (function(){

    function createClientConfig() {
        var conf = new kalturaClientBase.KalturaConfiguration(partnerId);
        conf.serviceUrl = config.get('backendClient').serviceUrl;
        return conf;
    }

    function convertToMs(minutes) {
        return minutes * 60 * 1000;
    }

    var lastSessionTime = null;
    var adminSecret = config.get('backendClient').adminSecret;
    var partnerId = config.get('backendClient').partnerId;
    var mediaServerHostname = config.get('mediaServer').hostname;
    var applicationName = config.get('mediaServer').applicationName;
    var client = null;
    var clientConfig = createClientConfig();
    var sessionDuration = convertToMs(config.get('backendClient').ksSessionRefreshIntervalMinutes);
    var BackendClient = {};
    var mediaServerIndexPromise = null;

    function printAPIResponse(logger, result, headers) {
        logger.info("API call headers: %j", headers);
        if(result)
            logger.info("API call result: %j", result);
    }

    function createSession() {
        var deferred = Q.defer();
        var now = new Date();
        //create session
        if (!lastSessionTime || (now - lastSessionTime) > sessionDuration) {
            moduleLogger.debug("Request for createSession started");
            client = new kalturaClient.KalturaClient(clientConfig);
            client.session.start(function(results, err, headers) {
                var endTime  = new Date();
                var operationTime = endTime - now;
                moduleLogger.debug("Request for createSession took %s", operationTime);
                if (err) {
                    moduleLogger.error("Failed to create session: %j", err);
                    printAPIResponse(moduleLogger, results, headers);
                    deferred.reject(err);
                }
                if (results) {
                    lastSessionTime = now;
                    moduleLogger.info("session created successfully %j", results);
                    client.setSessionId(results);
                    deferred.resolve();
                }
            }, adminSecret, null, kalturaTypes.KalturaSessionType.ADMIN, partnerId, null, null);
        }
        else {
            deferred.resolve();
        }

        return deferred.promise;
    }

    function getMediaServerIdPromise() {
        if (mediaServerIndexPromise) {
            return mediaServerIndexPromise;
        }

        var deferred = Q.defer();

        //get serverNode id by mediaServerHostName
        var serverNodeFilter = new kalturaVO.KalturaWowzaMediaServerNodeFilter();
        serverNodeFilter.hostNameLike = mediaServerHostname;

        client.serverNode.listAction(function(results,err,headers) {
            if (err) {
                moduleLogger.error("Failed to retrieve serverNodeIndex for host %s with error %s", mediaServerHostname, err);
                printAPIResponse(moduleLogger, results, headers);
                deferred.reject(err);
            }
            if (results && results.objects[0] && results.objects[0].objectType !== 'KalturaAPIException') {
                var serverNode = results.objects[0];
                moduleLogger.info("successfully retrieve serverNodeId for host name %s id %s", mediaServerHostname, serverNode.id);
                deferred.resolve(serverNode.id);
            }
        }, serverNodeFilter);

        mediaServerIndexPromise=deferred.promise;

        return mediaServerIndexPromise;
    }

    function convertKalturaEntry(item){
        var res = {
          "entryId" : item.id,
          "flavorParamsIds" : item.flavorParamsIds
            // TODO: Retreive ServerIndex! -> Gad
        };
        if (item.dvrStatus === kalturaTypes.KalturaDVRStatus.ENABLED) {

            if (item.dvrWindow) {
                var entryDVRWindow = item.dvrWindow * 60;     //   assuming dvrWindow from backend is in minutes!
                res.dvrWindow = Math.max(config.get("minimalDvrWindow"), entryDVRWindow);

            }
            else {
                res.dvrWindow = config.get("defaultDvrWindow");
            }

            res.maxChunkCount = config.get("dvrMaxChunkCount");
        }
        else {
            res.maxChunkCount = config.get("liveMaxChunkCount");
        }
        return res;
    }

    function getLiveEntries() {
        var deferred = Q.defer();
        var filter = new kalturaVO.KalturaLiveStreamEntryFilter();
        filter.isLive = kalturaTypes.KalturaNullableBoolean.TRUE_VALUE;
        filter.hasMediaServerHostname = mediaServerHostname;
        var pager = {
            pageSize : 300,
            pageIndex : 1
        };
        var startTime = new Date();
        moduleLogger.debug("Request for liveStream.listAction started");
        client.liveStream.listAction(function(results, err, headers) {
            var endTime = new Date();
            var operationTime = endTime - startTime;
            moduleLogger.debug("Request for liveStream.listAction took %s", operationTime);
            if (results) {
                var objs = _.map(results.objects, convertKalturaEntry);
                moduleLogger.debug("Got live entries: %j", objs);
                deferred.resolve(objs);
            }
            else {
                printAPIResponse(moduleLogger, results, headers);
                moduleLogger.error("Failed to get live entries: %s", err);
                deferred.reject(new Error("Failed to retrieve live entries from server"));
            }
        }, filter, pager);

        return deferred.promise;
    }

    function getEntryInfo(entryId, serverNodeId) {

        var deferred = Q.defer();

        //get live stream entry by Entry ID
        var startTime = new Date();
        client.liveStream.get(function(result, err, headers) {
            var endTime = new Date();
            var operationTime = endTime - startTime;
            moduleLogger.info("Got server node info for entry %s (took %d)", entryId, operationTime);
            printAPIResponse(moduleLogger, result, headers);

            if (result.objectType !== "KalturaAPIException") {  //Use to indicate success operation
                var liveEntry = convertKalturaEntry(result);

                if(result.primaryServerNodeId === serverNodeId)
                    liveEntry.serverType = kalturaTypes.KalturaEntryServerNodeType.LIVE_PRIMARY;
                else
                    liveEntry.serverType = kalturaTypes.KalturaEntryServerNodeType.LIVE_BACKUP;
                deferred.resolve(liveEntry);
            }
            else {
                moduleLogger.error("Failed to retrieve live stream entry info for from server: %s", result[0].message);
                deferred.reject(new Error("%s: %s", result.objectType, result.code));
            }
        }, entryId);

        return deferred.promise;
    }

    function registerEntryInDatabase(entryId, serverIndex, state, event, logger) {
        var deferred = Q.defer();
        logger.debug("Request for register media server started");
        client.liveStream.registerMediaServer(function(result, err, headers) {
            if (result.objectType === "KalturaLiveStreamEntry") {  //Use to indicate success operation
                logger.info("Register media server for entry finished successfully - '%s'", event.toUpperCase());
                deferred.resolve(result);   //check which object, if any, need to pass.
            }
            else {
                printAPIResponse(logger, result, headers);
                logger.error("Failed to register media server - '%s' - for entry. Error: %s", event.toUpperCase(), result.message);
                deferred.reject(new Error(result.objectType + ": " + result.code));
            }
        }, entryId, mediaServerHostname, serverIndex, applicationName , state);
        return deferred.promise;
    }

    function unregisterEntryInDatabase(entryId, serverIndex, logger) {
        var deferred = Q.defer();
        logger.debug("Request for unregister media server started");
        client.liveStream.unregisterMediaServer(function(result, err, headers) {
            if (result.objectType === "KalturaLiveStreamEntry") {  //Use to indicate success operation
                logger.info("Unregister media server for entry finished successfully");
                deferred.resolve(result);   //check which object, if any, need to pass.
            }
            else {
                printAPIResponse(logger, result, headers);
                logger.error("Failed to unregister media from server: %s", result.message);
                deferred.reject(new Error("%s: %s", result.objectType, result.code));
            }
        }, entryId, mediaServerHostname, serverIndex, applicationName);
        return deferred.promise;
    }

    BackendClient.getLiveEntriesForMediaServer = function() {
       return createSession()
           .then(function() {
                return getLiveEntries();
            });
    };

    BackendClient.getEntries = function(entryId) {
        return createSession()
            .then(function () {
                return getMediaServerIdPromise().then(function(index) {
                    return getEntryInfo(entryId, index);
                });
            });
    };

    BackendClient.registerEntryInDatabase = function(entryObject, state, event, logger) {
        logger.info("Calling registerMediaServer, updating entry in database");
        return createSession()
            .then(function() {
                // TODO: Change hard coded 1 value to serverIndex parameter -> Gad
                return registerEntryInDatabase(entryObject.entryId, entryObject.serverType, state, event, logger);
            });
    };

    BackendClient.unregisterEntryInDatabase = function(entryId, logger) {
        logger.debug("Calling unregisterMediaServer, and delete entry from database");
        return createSession()
            .then(function() {
                return unregisterEntryInDatabase(entryId, logger);
            });

    };

    return BackendClient;
})();

module.exports = BackendClient;
<|endoftext|>


<commit_before>var fs = require("fs");
var path = require("path");
var util = require("util");
var crypto = require("crypto");

/**
 * 由于非常依赖promise，所以将promise设置为全局变量
 * @type {[type]}
 */
global.Promise = require('es6-promise').Promise;

/**
 * 动态创建一个类
 * 提供了继承、扩展、调用父级别方法等方法
 * @return {[type]} [description]
 */
global.Class = function (prop) {
	var cls = function () {
		function T(args) {
			if(typeof this.init == 'function'){
				//获取init返回值，如果返回一个promise，可以让后续执行在then之后
				this.__initReturn = this.init.apply(this, args);
			}
			return this;
		}
		var _t = arguments.callee;
		T.prototype = _t.prototype;
		T.constructor = _t;
		return new T(arguments);
	};
	cls.extend = function(pro){
		extend(this.prototype, pro);
		return this;
	};
	cls.inherits = function(superCls){
		util.inherits(this, superCls);
		return this;
	}
	//调用父级方法
	cls.prototype.super_ = function(name, data){
		if (!this[name]) {
			return false;
		};
		if (!isArray(data)) {
			data = [data];
		};
		var super_ = this.constructor.super_;
		while(1){
			if (this[name] === super_.prototype[name] && super_.super_) {
				super_ = super_.super_;
			}else{
				break;
			}
		}
		var method = super_.prototype[name];
		delete super_.prototype[name];
		var ret =  method.apply(this, data);
		super_.prototype[name] = method;
		return ret;
	};
	extend(cls.prototype, prop);
	// if (typeof prop == 'function') {
	//     prop = prop();
	// };
	// prop = prop || {};
	// for(var name in prop){
	//     cls.prototype[name] = prop[name];
	// }
	return cls;
}
/**
 * extend, from jquery
 * @return {[type]} [description]
 */
global.extend = function(){
	var args = [].slice.call(arguments);
	var deep = true;
	var target = args.shift();
	if (isBoolean(target)) {
		deep = target;
		target = args.shift();
	};
	target = target || {};
	var length = args.length;
	var options, name, src, copy, copyAsArray, clone;
	for(var i = 0; i < length; i++){
		options = args[i] || {};
		if (isFunction(options)) {
			options = options();
		};
		for(name in options){
			src = target[name];
			copy = options[name];
			if (src === copy) {
				continue;
			};
			if (deep && copy && (isObject(copy) || (copyAsArray = isArray(copy) ))) {
				if (copyAsArray) {
					copyAsArray = false;
					clone = src && isArray(src) ? src : [];
				}else{
					clone = src && isObject(src) ? src : {};
				}
				target[name] = extend(deep, clone, copy);
			}else if (copy !== undefined) {
				target[name] = copy;
			};
		}
	}
	return target;
}

// global.extend = function(origin, add){
//     if (typeof add == 'function') {
//         add = add();
//     };
//     return util._extend(origin || {}, add);
// };

/**
 * 是否是boolean
 * @param  {[type]}  obj
 * @return {Boolean}
 */
global.isBoolean = function(obj){
	return obj === true || obj === false;
}
//Object上toString方法
var toString = Object.prototype.toString;
/**
 * 是否是数字
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isNumber = function(obj){
	return toString.call(obj) === '[object Number]';
}
/**
 * 是否是个对象
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isObject = function(obj){
	return toString.call(obj) === '[object Object]';
}
/**
 * 是否是字符串
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isString = function(obj){
	return toString.call(obj) === '[object String]';
}
/**
 * 是否是个function
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isFunction = function(obj){
	return typeof obj === 'function';
}
/**
 * 是否是日期
 * @return {Boolean} [description]
 */
global.isDate = function(obj){
	return util.isDate(obj);
}
/**
 * 是否是正则
 * @param  {[type]}  reg [description]
 * @return {Boolean}     [description]
 */
global.isRegexp = function(obj){
	return util.isRegExp(obj);
}
/**
 * 是否是个错误
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isError = function(obj){
	return util.isError(obj);
}
/**
 * 判断对象是否为空
 * @param  {[type]}  obj
 * @return {Boolean}
 */
global.isEmpty = function(obj){
	if (isObject(obj)) {
		return Object.keys(obj).length === 0;
	}else if (isArray(obj)) {
		return obj.length === 0;
	}else if (isString(obj)) {
		return obj.length === 0;
	}else if (isNumber(obj)) {
		return obj === 0;
	}else if (obj === null || obj === undefined) {
		return true;
	}else if (isBoolean(obj)) {
		return !obj;
	};
	return false;
}
/**
 * 是否是个标量
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isScalar = function(obj){
	return isBoolean(obj) || isNumber(obj) || isString(obj);
}
/**
 * 是否是个数组
 * @type {Boolean}
 */
global.isArray = Array.isArray;
/**
 * 是否是个文件
 * @param  {[type]}  p [description]
 * @return {Boolean}   [description]
 */
global.isFile = function(p){
	if (!fs.existsSync(p)) {
		return false;
	};
	var stats = fs.statSync(p);
	return stats.isFile();
}
/**
 * 是否是个目录
 * @param  {[type]}  p [description]
 * @return {Boolean}   [description]
 */
global.isDir = function(p){
	if (!fs.existsSync(p)) {
		return false;
	};
	var stats = fs.statSync(p);
	return stats.isDirectory();
}
/**
 * 是否是个数字的字符串
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
var numberReg = /^((\d*\.?\d*(?:e[+-]?\d*(?:\d?\.?|\.?\d?)\d*)?)|(0[0-7]+)|(0x[0-9a-f]+))$/i;
global.isNumberString = function(obj){
	return numberReg.test(obj);
}
/**
 * 判断是否是个promise
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isPromise = function(obj){
	return obj && typeof obj.then === 'function';
}

/**
 * 判断一个文件或者目录是否可写
 * @param  {[type]}  p [description]
 * @return {Boolean}      [description]
 */
global.isWritable = function(p){
	if (!fs.existsSync(p)) {
		return false;
	};
	var stats = fs.statSync(p);
	var mode = stats.mode;
	var uid = process.getuid ? process.getuid() : 0;
	var gid = process.getgid ? process.getgid() : 0;
	var owner = uid == stats.uid;
	var group = gid == stats.gid;
	return owner && (mode & 00200) || // User is owner and owner can write.
			group && (mode & 00020) || // User is in group and group can write.
		 (mode & 00002); // Anyone can write.
}

/**
 * 递归创建目录，同步模式
 * @param  {[type]} p    [description]
 * @param  {[type]} mode [description]
 * @return {[type]}      [description]
 */
global.mkdir = function(p, mode){
	mode = mode || '0755';
	if (fs.existsSync(p)) {
		chmod(p, mode);
		return true;
	};
	var pp = path.dirname(p);
	if (fs.existsSync(pp)) {
		fs.mkdirSync(p, mode);
	}else{
		mkdir(pp, mode);
		mkdir(p, mode);
	}
	return true;
}
/**
 * 修改目录或者文件权限
 * @param  {[type]} p    [description]
 * @param  {[type]} mode [description]
 * @return {[type]}      [description]
 */
global.chmod = function(p, mode){
	mode = mode || '0755';
	if (!fs.existsSync(p)) {
		return true;
	};
	return fs.chmodSync(p, mode);
}
/**
 * 获取文件内容
 * @param  {[type]} file [description]
 * @return {[type]}      [description]
 */
global.getFileContent = function(file){
	if (!fs.existsSync(file)) {
		return '';
	};
	var encoding = C("encoding") || "utf8";
	return fs.readFileSync(file, encoding);
}
/**
 * 设置文件内容
 * @param  {[type]} file [description]
 * @param  {[type]} data [description]
 * @return {[type]}      [description]
 */
global.setFileContent = function(file, data){
	return fs.writeFileSync(file, data);
}
/**
 * 大写首字符
 * @param  {[type]} name [description]
 * @return {[type]}      [description]
 */
global.ucfirst = function(name){
	name = name || "";
	return name.substr(0,1).toUpperCase() + name.substr(1).toLowerCase();
}
/**
 * 获取字符串的md5
 * @param  {[type]} str [description]
 * @return {[type]}     [description]
 */
global.md5 = function(str){
	var instance = crypto.createHash('md5');
	instance.update(str);
	return instance.digest('hex');
}
/**
 * 字符串命名风格转换
 * @param  {[type]} name [description]
 * @param  {[type]} type [description]
 * @return {[type]}      [description]
 */
global.parseName = function(name, type){
	name = (name + "").trim();
	if (type == 1) {
		name = name.replace(/_([a-zA-Z])/g, function(a, b){
			return b.toUpperCase();
		});
		return name.substr(0, 1).toUpperCase() + name.substr(1);
	} else {
		//首字母如果是大写，不转义为_x
		if (name.length >= 1) {
			name = name.substr(0, 1).toLowerCase() + name.substr(1);
		};
		return name.replace(/[A-Z]/g, function(a){
			return "_" + a;
		}).toLowerCase();
	}
}
/**
 * 生成一个promise,如果传入的参数是promise则直接返回
 * @param  {[type]} obj [description]
 * @return {[type]}     [description]
 */
global.getPromise = function(obj, reject){
	if (isPromise(obj)) {
		return obj;
	};
	if (reject) {
		return Promise.reject(obj);
	};
	return Promise.resolve(obj);
}
/**
 * 生成一个defer对象
 * @return {[type]} [description]
 */
global.getDefer = function(){
	var deferred = {};
	deferred.promise = new Promise(function(resolve, reject){
		deferred.resolve = resolve;
		deferred.reject = reject;
	});
	return deferred;
}
/**
 * 快速生成一个object
 * @param  {[type]} key   [description]
 * @param  {[type]} value [description]
 * @return {[type]}       [description]
 */
global.getObject = function(key, value){
	var obj = {};
	if (!isArray(key)) {
		obj[key] = value;
		return obj;
	};
	key.forEach(function(item, i){
		obj[item] = value[i];
	})
	return obj;
}<commit_msg>update<commit_after>var fs = require("fs");
var path = require("path");
var util = require("util");
var crypto = require("crypto");

/**
 * 由于非常依赖promise，所以将promise设置为全局变量
 * @type {[type]}
 */
global.Promise = require('es6-promise').Promise;

/**
 * 动态创建一个类
 * 提供了继承、扩展、调用父级别方法等方法
 * @return {[type]} [description]
 */
global.Class = function (prop) {
	var cls = function () {
		function T(args) {
			if(typeof this.init == 'function'){
				//获取init返回值，如果返回一个promise，可以让后续执行在then之后
				this.__initReturn = this.init.apply(this, args);
			}
			return this;
		}
		var _t = arguments.callee;
		T.prototype = _t.prototype;
		T.constructor = _t;
		return new T(arguments);
	};
	cls.extend = function(pro){
		extend(this.prototype, pro);
		return this;
	};
	cls.inherits = function(superCls){
		util.inherits(this, superCls);
		return this;
	}
	//调用父级方法
	cls.prototype.super_ = function(name, data){
		if (!this[name]) {
			return false;
		};
		if (!isArray(data)) {
			data = [data];
		};
		var super_ = this.constructor.super_;
		while(1){
			if (this[name] === super_.prototype[name] && super_.super_) {
				super_ = super_.super_;
			}else{
				break;
			}
		}
		var method = super_.prototype[name];
		delete super_.prototype[name];
		var ret =  method.apply(this, data);
		super_.prototype[name] = method;
		return ret;
	};
	extend(cls.prototype, prop);
	// if (typeof prop == 'function') {
	//     prop = prop();
	// };
	// prop = prop || {};
	// for(var name in prop){
	//     cls.prototype[name] = prop[name];
	// }
	return cls;
}
/**
 * extend, from jquery
 * @return {[type]} [description]
 */
global.extend = function(){
	var args = [].slice.call(arguments);
	var deep = true;
	var target = args.shift();
	if (isBoolean(target)) {
		deep = target;
		target = args.shift();
	};
	target = target || {};
	var length = args.length;
	var options, name, src, copy, copyAsArray, clone;
	for(var i = 0; i < length; i++){
		options = args[i] || {};
		if (isFunction(options)) {
			options = options();
		};
		for(name in options){
			src = target[name];
			copy = options[name];
			if (src === copy) {
				continue;
			};
			if (deep && copy && (isObject(copy) || (copyAsArray = isArray(copy) ))) {
				if (copyAsArray) {
					copyAsArray = false;
					clone = src && isArray(src) ? src : [];
				}else{
					clone = src && isObject(src) ? src : {};
				}
				target[name] = extend(deep, clone, copy);
			}else if (copy !== undefined) {
				target[name] = copy;
			};
		}
	}
	return target;
}

// global.extend = function(origin, add){
//     if (typeof add == 'function') {
//         add = add();
//     };
//     return util._extend(origin || {}, add);
// };

/**
 * 是否是boolean
 * @param  {[type]}  obj
 * @return {Boolean}
 */
global.isBoolean = function(obj){
	return obj === true || obj === false;
}
//Object上toString方法
var toString = Object.prototype.toString;
/**
 * 是否是数字
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isNumber = function(obj){
	return toString.call(obj) === '[object Number]';
}
/**
 * 是否是个对象
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isObject = function(obj){
	return toString.call(obj) === '[object Object]';
}
/**
 * 是否是字符串
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isString = function(obj){
	return toString.call(obj) === '[object String]';
}
/**
 * 是否是个function
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isFunction = function(obj){
	return typeof obj === 'function';
}
/**
 * 是否是日期
 * @return {Boolean} [description]
 */
global.isDate = function(obj){
	return util.isDate(obj);
}
/**
 * 是否是正则
 * @param  {[type]}  reg [description]
 * @return {Boolean}     [description]
 */
global.isRegexp = function(obj){
	return util.isRegExp(obj);
}
/**
 * 是否是个错误
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isError = function(obj){
	return util.isError(obj);
}
/**
 * 判断对象是否为空
 * @param  {[type]}  obj
 * @return {Boolean}
 */
global.isEmpty = function(obj){
	if (isObject(obj)) {
		return Object.keys(obj).length === 0;
	}else if (isArray(obj)) {
		return obj.length === 0;
	}else if (isString(obj)) {
		return obj.length === 0;
	}else if (isNumber(obj)) {
		return obj === 0;
	}else if (obj === null || obj === undefined) {
		return true;
	}else if (isBoolean(obj)) {
		return !obj;
	};
	return false;
}
/**
 * 是否是个标量
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isScalar = function(obj){
	return isBoolean(obj) || isNumber(obj) || isString(obj);
}
/**
 * 是否是个数组
 * @type {Boolean}
 */
global.isArray = Array.isArray;
/**
 * 是否是个文件
 * @param  {[type]}  p [description]
 * @return {Boolean}   [description]
 */
global.isFile = function(p){
	if (!fs.existsSync(p)) {
		return false;
	};
	var stats = fs.statSync(p);
	return stats.isFile();
}
/**
 * 是否是个目录
 * @param  {[type]}  p [description]
 * @return {Boolean}   [description]
 */
global.isDir = function(p){
	if (!fs.existsSync(p)) {
		return false;
	};
	var stats = fs.statSync(p);
	return stats.isDirectory();
}
/**
 * 是否是个数字的字符串
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
var numberReg = /^((\d*\.?\d*(?:e[+-]?\d*(?:\d?\.?|\.?\d?)\d*)?)|(0[0-7]+)|(0x[0-9a-f]+))$/i;
global.isNumberString = function(obj){
	return numberReg.test(obj);
}
/**
 * 判断是否是个promise
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isPromise = function(obj){
	return obj && typeof obj.then === 'function';
}

/**
 * 判断一个文件或者目录是否可写
 * @param  {[type]}  p [description]
 * @return {Boolean}      [description]
 */
global.isWritable = function(p){
	if (!fs.existsSync(p)) {
		return false;
	};
	var stats = fs.statSync(p);
	var mode = stats.mode;
	var uid = process.getuid ? process.getuid() : 0;
	var gid = process.getgid ? process.getgid() : 0;
	var owner = uid == stats.uid;
	var group = gid == stats.gid;
	return owner && (mode & 00200) || // User is owner and owner can write.
			group && (mode & 00020) || // User is in group and group can write.
		 (mode & 00002); // Anyone can write.
}

/**
 * 递归创建目录，同步模式
 * @param  {[type]} p    [description]
 * @param  {[type]} mode [description]
 * @return {[type]}      [description]
 */
global.mkdir = function(p, mode){
	mode = mode || '0755';
	if (fs.existsSync(p)) {
		chmod(p, mode);
		return true;
	};
	var pp = path.dirname(p);
	if (fs.existsSync(pp)) {
		fs.mkdirSync(p, mode);
	}else{
		mkdir(pp, mode);
		mkdir(p, mode);
	}
	return true;
}
/**
 * 修改目录或者文件权限
 * @param  {[type]} p    [description]
 * @param  {[type]} mode [description]
 * @return {[type]}      [description]
 */
global.chmod = function(p, mode){
	mode = mode || '0755';
	if (!fs.existsSync(p)) {
		return true;
	};
	return fs.chmodSync(p, mode);
}
/**
 * 获取文件内容
 * @param  {[type]} file [description]
 * @return {[type]}      [description]
 */
global.getFileContent = function(file){
	if (!fs.existsSync(file)) {
		return '';
	};
	var encoding = C("encoding") || "utf8";
	return fs.readFileSync(file, encoding);
}
/**
 * 设置文件内容
 * @param  {[type]} file [description]
 * @param  {[type]} data [description]
 * @return {[type]}      [description]
 */
global.setFileContent = function(file, data){
	return fs.writeFileSync(file, data);
}
/**
 * 大写首字符
 * @param  {[type]} name [description]
 * @return {[type]}      [description]
 */
global.ucfirst = function(name){
	name = name || "";
	return name.substr(0,1).toUpperCase() + name.substr(1).toLowerCase();
}
/**
 * 获取字符串的md5
 * @param  {[type]} str [description]
 * @return {[type]}     [description]
 */
global.md5 = function(str){
	var instance = crypto.createHash('md5');
	instance.update(str);
	return instance.digest('hex');
}
/**
 * 字符串命名风格转换
 * @param  {[type]} name [description]
 * @param  {[type]} type [description]
 * @return {[type]}      [description]
 */
global.parseName = function(name, type){
	name = (name + "").trim();
	if (type == 1) {
		name = name.replace(/_([a-zA-Z])/g, function(a, b){
			return b.toUpperCase();
		});
		return name.substr(0, 1).toUpperCase() + name.substr(1);
	} else {
		//首字母如果是大写，不转义为_x
		if (name.length >= 1) {
			name = name.substr(0, 1).toLowerCase() + name.substr(1);
		};
		return name.replace(/[A-Z]/g, function(a){
			return "_" + a;
		}).toLowerCase();
	}
}
/**
 * 生成一个promise,如果传入的参数是promise则直接返回
 * @param  {[type]} obj [description]
 * @return {[type]}     [description]
 */
global.getPromise = function(obj, reject){
	if (isPromise(obj)) {
		return obj;
	};
	if (reject) {
		return Promise.reject(obj);
	};
	return Promise.resolve(obj);
}
/**
 * 生成一个defer对象
 * @return {[type]} [description]
 */
global.getDefer = function(){
	var deferred = {};
	deferred.promise = new Promise(function(resolve, reject){
		deferred.resolve = resolve;
		deferred.reject = reject;
	});
	return deferred;
}
/**
 * 快速生成一个object
 * @param  {[type]} key   [description]
 * @param  {[type]} value [description]
 * @return {[type]}       [description]
 */
global.getObject = function(key, value){
	var obj = {};
	if (!isArray(key)) {
		obj[key] = value;
		return obj;
	};
	key.forEach(function(item, i){
		obj[item] = value[i];
	})
	return obj;
}<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var util = require('util');
var crypto = require('crypto');
var net = require('net');

/**
 * 由于非常依赖promise，所以将promise设置为全局变量
 * @type {[type]}
 */
global.Promise = require('es6-promise').Promise;

/**
 * 动态创建一个类
 * 提供了继承、扩展、调用父级别方法等方法
 * @return {[type]} [description]
 */
global.Class = function (prop, superCls) {
  'use strict';
  var cls = function () {
    function T(args) {
      for(var name in cls.__prop){
        var val = cls.__prop[name];
        this[name] = isObject(val) ? extend({}, val) : val;
      }
      //自动执行init方法
      if(isFunction(this.init)){
        //获取init返回值，如果返回一个promise，可以让后续执行在then之后
        this.__initReturn = this.init.apply(this, args);
      }
      return this;
    }
    T.prototype = cls.prototype;
    T.constructor = cls;
    return new T(arguments);
  };
  //类的属性，不放在原型上，实例化的时候调用
  cls.__prop = {};
  cls.extend = function(prop){
    if (isFunction(prop)) {
      prop = prop();
    }
    if (isObject(prop)) {
      for(var name in prop){
        var val = prop[name];
        if (isFunction(val)) {
          this.prototype[name] = val;
        }else{
          cls.__prop[name] = isObject(val) ? extend({}, val) : val;
        }
      }
    }
    return this;
  };
  cls.inherits = function(superCls){
    util.inherits(this, superCls);
    //将父级的属性复制到当前类上
    extend(cls.__prop, superCls.__prop);
    return this;
  };
  if (superCls === true && isFunction(prop)) {
    superCls = prop;
    prop = undefined;
  }
  if (isFunction(superCls)) {
    cls.inherits(superCls);
  }
  //调用父级方法
  cls.prototype.super = cls.prototype.super_ = function(name, data){
    if (!this[name]) {
      return;
    }
    if (!isArray(data)) {
      data = [data];
    }
    var super_ = this.constructor.super_;
    while(1){
      if (this[name] === super_.prototype[name] && super_.super_) {
        super_ = super_.super_;
      }else{
        break;
      }
    }
    var method = super_.prototype[name];
    delete super_.prototype[name];
    var ret =  method.apply(this, data);
    super_.prototype[name] = method;
    return ret;
  };
  if (prop) {
    cls.extend(prop);
  }
  return cls;
};
/**
 * extend, from jquery，具有深度复制功能
 * @return {[type]} [description]
 */
global.extend = function(){
  'use strict';
  var args = [].slice.call(arguments);
  var deep = true;
  var target = args.shift();
  if (isBoolean(target)) {
    deep = target;
    target = args.shift();
  }
  target = target || {};
  var length = args.length;
  var options, name, src, copy, copyAsArray, clone;
  for(var i = 0; i < length; i++){
    options = args[i] || {};
    if (isFunction(options)) {
      options = options();
    }
    for(name in options){
      src = target[name];
      copy = options[name];
      if (src === copy) {
        continue;
      }
      if (deep && copy && (isObject(copy) || (copyAsArray = isArray(copy) ))) {
        if (copyAsArray) {
          copyAsArray = false;
          clone = src && isArray(src) ? src : [];
        }else{
          clone = src && isObject(src) ? src : {};
        }
        target[name] = extend(deep, clone, copy);
      }else if (copy !== undefined) {
        target[name] = copy;
      }
    }
  }
  return target;
};

//Object上toString方法
var toString = Object.prototype.toString;

/**
 * 是否是boolean
 * @param  {[type]}  obj
 * @return {Boolean}
 */
global.isBoolean = function(obj){
  'use strict';
  return toString.call(obj) === '[object Boolean]';
};
/**
 * 是否是数字
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isNumber = function(obj){
  'use strict';
  return toString.call(obj) === '[object Number]';
};
/**
 * 是否是个对象
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isObject = function(obj){
  'use strict';
  return toString.call(obj) === '[object Object]';
};
/**
 * 是否是字符串
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isString = function(obj){
  'use strict';
  return toString.call(obj) === '[object String]';
};
/**
 * 是否是个function
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isFunction = function(obj){
  'use strict';
  return typeof obj === 'function';
};
/**
 * 是否是日期
 * @return {Boolean} [description]
 */
global.isDate = function(obj){
  'use strict';
  return util.isDate(obj);
};
/**
 * 是否是正则
 * @param  {[type]}  reg [description]
 * @return {Boolean}     [description]
 */
global.isRegexp = function(obj){
  'use strict';
  return util.isRegExp(obj);
};
/**
 * 是否是个错误
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isError = function(obj){
  'use strict';
  return util.isError(obj);
};
/**
 * 判断对象是否为空
 * @param  {[type]}  obj
 * @return {Boolean}
 */
global.isEmpty = function(obj){
  'use strict';
  if (isObject(obj)) {
    var key;
    for(key in obj){
      return false;
    }
    return true;
  }else if (isArray(obj)) {
    return obj.length === 0;
  }else if (isString(obj)) {
    return obj.length === 0;
  }else if (isNumber(obj)) {
    return obj === 0;
  }else if (obj === null || obj === undefined) {
    return true;
  }else if (isBoolean(obj)) {
    return !obj;
  }
  return false;
};
/**
 * 是否是个标量
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isScalar = function(obj){
  'use strict';
  return isBoolean(obj) || isNumber(obj) || isString(obj);
};
/**
 * 是否是个数组
 * @type {Boolean}
 */
global.isArray = Array.isArray;
/**
 * 是否是IP
 * @type {Boolean}
 */
global.isIP = net.isIP;
global.isIP4 = net.isIP4;
global.isIP6 = net.isIP6;
/**
 * 是否是个文件
 * @param  {[type]}  p [description]
 * @return {Boolean}   [description]
 */
global.isFile = function(p){
  'use strict';
  if (!fs.existsSync(p)) {
    return false;
  }
  var stats = fs.statSync(p);
  return stats.isFile();
};
/**
 * 是否是个目录
 * @param  {[type]}  p [description]
 * @return {Boolean}   [description]
 */
global.isDir = function(p){
  'use strict';
  if (!fs.existsSync(p)) {
    return false;
  }
  var stats = fs.statSync(p);
  return stats.isDirectory();
};
/**
 * 是否是buffer
 * @type {Boolean}
 */
global.isBuffer = Buffer.isBuffer;
/**
 * 是否是个数字的字符串
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
var numberReg = /^((\d*\.?\d*(?:e[+-]?\d*(?:\d?\.?|\.?\d?)\d*)?)|(0[0-7]+)|(0x[0-9a-f]+))$/i;
global.isNumberString = function(obj){
  'use strict';
  return numberReg.test(obj);
};
/**
 * 判断是否是个promise
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isPromise = function(obj){
  'use strict';
  return obj && typeof obj.then === 'function';
};

/**
 * 判断一个文件或者目录是否可写
 * @param  {[type]}  p [description]
 * @return {Boolean}      [description]
 */
global.isWritable = function(p){
  'use strict';
  if (!fs.existsSync(p)) {
    return false;
  }
  var stats = fs.statSync(p);
  var mode = stats.mode;
  var uid = process.getuid ? process.getuid() : 0;
  var gid = process.getgid ? process.getgid() : 0;
  var owner = uid === stats.uid;
  var group = gid === stats.gid;
  return owner && (mode & parseInt('00200', 8)) ||
      group && (mode & parseInt('00020', 8)) ||
      (mode & parseInt('00002', 8));
};

/**
 * 递归创建目录，同步模式
 * @param  {[type]} p    [description]
 * @param  {[type]} mode [description]
 * @return {[type]}      [description]
 */
global.mkdir = function(p, mode){
  'use strict';
  mode = mode || '0777';
  if (fs.existsSync(p)) {
    chmod(p, mode);
    return true;
  }
  var pp = path.dirname(p);
  if (fs.existsSync(pp)) {
    fs.mkdirSync(p, mode);
  }else{
    mkdir(pp, mode);
    mkdir(p, mode);
  }
  return true;
};
/**
 * 修改目录或者文件权限
 * @param  {[type]} p    [description]
 * @param  {[type]} mode [description]
 * @return {[type]}      [description]
 */
global.chmod = function(p, mode){
  'use strict';
  mode = mode || '0777';
  if (!fs.existsSync(p)) {
    return true;
  }
  return fs.chmodSync(p, mode);
};
/**
 * 获取文件内容
 * @param  {[type]} file [description]
 * @return {[type]}      [description]
 */
global.getFileContent = function(file, encoding){
  'use strict';
  if (!fs.existsSync(file)) {
    return '';
  }
  return fs.readFileSync(file, {
    encoding: encoding || 'utf8'
  });
};
/**
 * 设置文件内容
 * @param  {[type]} file [description]
 * @param  {[type]} data [description]
 * @return {[type]}      [description]
 */
global.setFileContent = function(file, data){
  'use strict';
  return fs.writeFileSync(file, data);
};
/**
 * 大写首字符
 * @param  {[type]} name [description]
 * @return {[type]}      [description]
 */
global.ucfirst = function(name){
  'use strict';
  name = name || '';
  return name.substr(0,1).toUpperCase() + name.substr(1).toLowerCase();
};
/**
 * 获取字符串的md5
 * @param  {[type]} str [description]
 * @return {[type]}     [description]
 */
global.md5 = function(str){
  'use strict';
  var instance = crypto.createHash('md5');
  instance.update(str + '');
  return instance.digest('hex');
};
/**
 * 生成一个promise,如果传入的参数是promise则直接返回
 * @param  {[type]} obj [description]
 * @return {[type]}     [description]
 */
global.getPromise = function(obj, reject){
  'use strict';
  if (isPromise(obj)) {
    return obj;
  }
  if (reject) {
    return Promise.reject(obj);
  }
  return Promise.resolve(obj);
};
/**
 * 生成一个defer对象
 * @return {[type]} [description]
 */
global.getDefer = function(){
  'use strict';
  var deferred = {};
  deferred.promise = new Promise(function(resolve, reject){
    deferred.resolve = resolve;
    deferred.reject = reject;
  });
  return deferred;
};
/**
 * 快速生成一个object
 * @param  {[type]} key   [description]
 * @param  {[type]} value [description]
 * @return {[type]}       [description]
 */
global.getObject = function(key, value){
  'use strict';
  var obj = {};
  if (!isArray(key)) {
    obj[key] = value;
    return obj;
  }
  key.forEach(function(item, i){
    obj[item] = value[i];
  });
  return obj;
};
/**
 * 将数组变成对象
 * @param  {[type]} arr       [description]
 * @param  {[type]} key       [description]
 * @param  {[type]} valueKeys [description]
 * @return {[type]}           [description]
 */
global.arrToObj = function(arr, key, valueKey){
  'use strict';
  var result = {};
  var arrResult = [];
  arr.forEach(function(item){
    var keyValue = item[key];
    if (valueKey === null) {
      arrResult.push(keyValue);
    }else if (valueKey) {
      result[keyValue] = item[valueKey];
    }else{
      result[keyValue] = item;
    }
  })
  return valueKey === null ? arrResult : result;
}<commit_msg>修正isWriteable<commit_after>var fs = require('fs');
var path = require('path');
var util = require('util');
var crypto = require('crypto');
var net = require('net');

/**
 * 由于非常依赖promise，所以将promise设置为全局变量
 * @type {[type]}
 */
global.Promise = require('es6-promise').Promise;

/**
 * 动态创建一个类
 * 提供了继承、扩展、调用父级别方法等方法
 * @return {[type]} [description]
 */
global.Class = function (prop, superCls) {
  'use strict';
  var cls = function () {
    function T(args) {
      for(var name in cls.__prop){
        var val = cls.__prop[name];
        this[name] = isObject(val) ? extend({}, val) : val;
      }
      //自动执行init方法
      if(isFunction(this.init)){
        //获取init返回值，如果返回一个promise，可以让后续执行在then之后
        this.__initReturn = this.init.apply(this, args);
      }
      return this;
    }
    T.prototype = cls.prototype;
    T.constructor = cls;
    return new T(arguments);
  };
  //类的属性，不放在原型上，实例化的时候调用
  cls.__prop = {};
  cls.extend = function(prop){
    if (isFunction(prop)) {
      prop = prop();
    }
    if (isObject(prop)) {
      for(var name in prop){
        var val = prop[name];
        if (isFunction(val)) {
          this.prototype[name] = val;
        }else{
          cls.__prop[name] = isObject(val) ? extend({}, val) : val;
        }
      }
    }
    return this;
  };
  cls.inherits = function(superCls){
    util.inherits(this, superCls);
    //将父级的属性复制到当前类上
    extend(cls.__prop, superCls.__prop);
    return this;
  };
  if (superCls === true && isFunction(prop)) {
    superCls = prop;
    prop = undefined;
  }
  if (isFunction(superCls)) {
    cls.inherits(superCls);
  }
  //调用父级方法
  cls.prototype.super = cls.prototype.super_ = function(name, data){
    if (!this[name]) {
      return;
    }
    if (!isArray(data)) {
      data = [data];
    }
    var super_ = this.constructor.super_;
    while(1){
      if (this[name] === super_.prototype[name] && super_.super_) {
        super_ = super_.super_;
      }else{
        break;
      }
    }
    var method = super_.prototype[name];
    delete super_.prototype[name];
    var ret =  method.apply(this, data);
    super_.prototype[name] = method;
    return ret;
  };
  if (prop) {
    cls.extend(prop);
  }
  return cls;
};
/**
 * extend, from jquery，具有深度复制功能
 * @return {[type]} [description]
 */
global.extend = function(){
  'use strict';
  var args = [].slice.call(arguments);
  var deep = true;
  var target = args.shift();
  if (isBoolean(target)) {
    deep = target;
    target = args.shift();
  }
  target = target || {};
  var length = args.length;
  var options, name, src, copy, copyAsArray, clone;
  for(var i = 0; i < length; i++){
    options = args[i] || {};
    if (isFunction(options)) {
      options = options();
    }
    for(name in options){
      src = target[name];
      copy = options[name];
      if (src === copy) {
        continue;
      }
      if (deep && copy && (isObject(copy) || (copyAsArray = isArray(copy) ))) {
        if (copyAsArray) {
          copyAsArray = false;
          clone = src && isArray(src) ? src : [];
        }else{
          clone = src && isObject(src) ? src : {};
        }
        target[name] = extend(deep, clone, copy);
      }else if (copy !== undefined) {
        target[name] = copy;
      }
    }
  }
  return target;
};

//Object上toString方法
var toString = Object.prototype.toString;

/**
 * 是否是boolean
 * @param  {[type]}  obj
 * @return {Boolean}
 */
global.isBoolean = function(obj){
  'use strict';
  return toString.call(obj) === '[object Boolean]';
};
/**
 * 是否是数字
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isNumber = function(obj){
  'use strict';
  return toString.call(obj) === '[object Number]';
};
/**
 * 是否是个对象
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isObject = function(obj){
  'use strict';
  return toString.call(obj) === '[object Object]';
};
/**
 * 是否是字符串
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isString = function(obj){
  'use strict';
  return toString.call(obj) === '[object String]';
};
/**
 * 是否是个function
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isFunction = function(obj){
  'use strict';
  return typeof obj === 'function';
};
/**
 * 是否是日期
 * @return {Boolean} [description]
 */
global.isDate = function(obj){
  'use strict';
  return util.isDate(obj);
};
/**
 * 是否是正则
 * @param  {[type]}  reg [description]
 * @return {Boolean}     [description]
 */
global.isRegexp = function(obj){
  'use strict';
  return util.isRegExp(obj);
};
/**
 * 是否是个错误
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isError = function(obj){
  'use strict';
  return util.isError(obj);
};
/**
 * 判断对象是否为空
 * @param  {[type]}  obj
 * @return {Boolean}
 */
global.isEmpty = function(obj){
  'use strict';
  if (isObject(obj)) {
    var key;
    for(key in obj){
      return false;
    }
    return true;
  }else if (isArray(obj)) {
    return obj.length === 0;
  }else if (isString(obj)) {
    return obj.length === 0;
  }else if (isNumber(obj)) {
    return obj === 0;
  }else if (obj === null || obj === undefined) {
    return true;
  }else if (isBoolean(obj)) {
    return !obj;
  }
  return false;
};
/**
 * 是否是个标量
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isScalar = function(obj){
  'use strict';
  return isBoolean(obj) || isNumber(obj) || isString(obj);
};
/**
 * 是否是个数组
 * @type {Boolean}
 */
global.isArray = Array.isArray;
/**
 * 是否是IP
 * @type {Boolean}
 */
global.isIP = net.isIP;
global.isIP4 = net.isIP4;
global.isIP6 = net.isIP6;
/**
 * 是否是个文件
 * @param  {[type]}  p [description]
 * @return {Boolean}   [description]
 */
global.isFile = function(p){
  'use strict';
  if (!fs.existsSync(p)) {
    return false;
  }
  var stats = fs.statSync(p);
  return stats.isFile();
};
/**
 * 是否是个目录
 * @param  {[type]}  p [description]
 * @return {Boolean}   [description]
 */
global.isDir = function(p){
  'use strict';
  if (!fs.existsSync(p)) {
    return false;
  }
  var stats = fs.statSync(p);
  return stats.isDirectory();
};
/**
 * 是否是buffer
 * @type {Boolean}
 */
global.isBuffer = Buffer.isBuffer;
/**
 * 是否是个数字的字符串
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
var numberReg = /^((\d*\.?\d*(?:e[+-]?\d*(?:\d?\.?|\.?\d?)\d*)?)|(0[0-7]+)|(0x[0-9a-f]+))$/i;
global.isNumberString = function(obj){
  'use strict';
  return numberReg.test(obj);
};
/**
 * 判断是否是个promise
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
global.isPromise = function(obj){
  'use strict';
  return obj && typeof obj.then === 'function';
};

/**
 * 判断一个文件或者目录是否可写
 * @param  {[type]}  p [description]
 * @return {Boolean}      [description]
 */
global.isWritable = function(p){
  'use strict';
  if (!fs.existsSync(p)) {
    return false;
  }
  var stats = fs.statSync(p);
  var mode = stats.mode;
  var uid = process.getuid ? process.getuid() : 0;
  var gid = process.getgid ? process.getgid() : 0;
  var owner = uid === stats.uid;
  var group = gid === stats.gid;
  return !!(owner && (mode & parseInt('00200', 8)) ||
      group && (mode & parseInt('00020', 8)) ||
      (mode & parseInt('00002', 8)));
};

/**
 * 递归创建目录，同步模式
 * @param  {[type]} p    [description]
 * @param  {[type]} mode [description]
 * @return {[type]}      [description]
 */
global.mkdir = function(p, mode){
  'use strict';
  mode = mode || '0777';
  if (fs.existsSync(p)) {
    chmod(p, mode);
    return true;
  }
  var pp = path.dirname(p);
  if (fs.existsSync(pp)) {
    fs.mkdirSync(p, mode);
  }else{
    mkdir(pp, mode);
    mkdir(p, mode);
  }
  return true;
};
/**
 * 修改目录或者文件权限
 * @param  {[type]} p    [description]
 * @param  {[type]} mode [description]
 * @return {[type]}      [description]
 */
global.chmod = function(p, mode){
  'use strict';
  mode = mode || '0777';
  if (!fs.existsSync(p)) {
    return true;
  }
  return fs.chmodSync(p, mode);
};
/**
 * 获取文件内容
 * @param  {[type]} file [description]
 * @return {[type]}      [description]
 */
global.getFileContent = function(file, encoding){
  'use strict';
  if (!fs.existsSync(file)) {
    return '';
  }
  return fs.readFileSync(file, {
    encoding: encoding || 'utf8'
  });
};
/**
 * 设置文件内容
 * @param  {[type]} file [description]
 * @param  {[type]} data [description]
 * @return {[type]}      [description]
 */
global.setFileContent = function(file, data){
  'use strict';
  return fs.writeFileSync(file, data);
};
/**
 * 大写首字符
 * @param  {[type]} name [description]
 * @return {[type]}      [description]
 */
global.ucfirst = function(name){
  'use strict';
  name = name || '';
  return name.substr(0,1).toUpperCase() + name.substr(1).toLowerCase();
};
/**
 * 获取字符串的md5
 * @param  {[type]} str [description]
 * @return {[type]}     [description]
 */
global.md5 = function(str){
  'use strict';
  var instance = crypto.createHash('md5');
  instance.update(str + '');
  return instance.digest('hex');
};
/**
 * 生成一个promise,如果传入的参数是promise则直接返回
 * @param  {[type]} obj [description]
 * @return {[type]}     [description]
 */
global.getPromise = function(obj, reject){
  'use strict';
  if (isPromise(obj)) {
    return obj;
  }
  if (reject) {
    return Promise.reject(obj);
  }
  return Promise.resolve(obj);
};
/**
 * 生成一个defer对象
 * @return {[type]} [description]
 */
global.getDefer = function(){
  'use strict';
  var deferred = {};
  deferred.promise = new Promise(function(resolve, reject){
    deferred.resolve = resolve;
    deferred.reject = reject;
  });
  return deferred;
};
/**
 * 快速生成一个object
 * @param  {[type]} key   [description]
 * @param  {[type]} value [description]
 * @return {[type]}       [description]
 */
global.getObject = function(key, value){
  'use strict';
  var obj = {};
  if (!isArray(key)) {
    obj[key] = value;
    return obj;
  }
  key.forEach(function(item, i){
    obj[item] = value[i];
  });
  return obj;
};
/**
 * 将数组变成对象
 * @param  {[type]} arr       [description]
 * @param  {[type]} key       [description]
 * @param  {[type]} valueKeys [description]
 * @return {[type]}           [description]
 */
global.arrToObj = function(arr, key, valueKey){
  'use strict';
  var result = {};
  var arrResult = [];
  arr.forEach(function(item){
    var keyValue = item[key];
    if (valueKey === null) {
      arrResult.push(keyValue);
    }else if (valueKey) {
      result[keyValue] = item[valueKey];
    }else{
      result[keyValue] = item;
    }
  })
  return valueKey === null ? arrResult : result;
}<|endoftext|>


<commit_before>/**
 * Converts CSV to Markdown Table
 *
 * @param {string} csvContent - The string content of the CSV
 * @param {string} delimiter - The character(s) to use as the CSV column delimiter
 * @param {boolean} hasHeader - Whether to use the first row of Data as headers
 * @returns {string}
 */
function csvToMarkdown(csvContent, delimiter, hasHeader) {
    if (delimiter === void 0) { delimiter = "\t"; }
    if (hasHeader === void 0) { hasHeader = false; }
    if (delimiter != "\t") {
        csvContent = csvContent.replace(/\t/g, "    ");
    }
    var columns = csvContent.split("\n");
    var tabularData = [];
    var maxRowLen = [];
    columns.forEach(function (e, i) {
        if (typeof tabularData[i] == "undefined") {
            tabularData[i] = [];
        }
        var regex = new RegExp('(?!\\B"[^"]*)' + delimiter + '(?![^"]*"\\B)');
        var row = e.split(regex);
        row.forEach(function (ee, ii) {
            if (typeof maxRowLen[ii] == "undefined") {
                maxRowLen[ii] = 0;
            }
            maxRowLen[ii] = Math.max(maxRowLen[ii], ee.length);
            tabularData[i][ii] = ee;
        });
    });
    var headerOutput = "";
    var seperatorOutput = "";
    maxRowLen.forEach(function (len) {
        var sizer = Array(len + 1 + 2);
        seperatorOutput += "|" + sizer.join("-");
        headerOutput += "|" + sizer.join(" ");
    });
    headerOutput += "| \n";
    seperatorOutput += "| \n";
    if (hasHeader) {
        headerOutput = "";
    }
    var rowOutput = "";
    tabularData.forEach(function (col, i) {
        maxRowLen.forEach(function (len, y) {
            var row = typeof col[y] == "undefined" ? "" : col[y];
            var spacing = Array((len - row.length) + 1).join(" ");
            var out = "| " + row + spacing + " ";
            if (hasHeader && i === 0) {
                headerOutput += out;
            }
            else {
                rowOutput += out;
            }
        });
        if (hasHeader && i === 0) {
            headerOutput += "| \n";
        }
        else {
            rowOutput += "| \n";
        }
    });
    return headerOutput + seperatorOutput + rowOutput;
}
if (typeof module != "undefined") {
    module.exports = csvToMarkdown;
}
<commit_msg>added strict<commit_after>"use strict";
/**
 * Converts CSV to Markdown Table
 *
 * @param {string} csvContent - The string content of the CSV
 * @param {string} delimiter - The character(s) to use as the CSV column delimiter
 * @param {boolean} hasHeader - Whether to use the first row of Data as headers
 * @returns {string}
 */
function csvToMarkdown(csvContent, delimiter, hasHeader) {
    if (delimiter === void 0) { delimiter = "\t"; }
    if (hasHeader === void 0) { hasHeader = false; }
    if (delimiter != "\t") {
        csvContent = csvContent.replace(/\t/g, "    ");
    }
    var columns = csvContent.split("\n");
    var tabularData = [];
    var maxRowLen = [];
    columns.forEach(function (e, i) {
        if (typeof tabularData[i] == "undefined") {
            tabularData[i] = [];
        }
        var regex = new RegExp('(?!\\B"[^"]*)' + delimiter + '(?![^"]*"\\B)');
        var row = e.split(regex);
        row.forEach(function (ee, ii) {
            if (typeof maxRowLen[ii] == "undefined") {
                maxRowLen[ii] = 0;
            }
            maxRowLen[ii] = Math.max(maxRowLen[ii], ee.length);
            tabularData[i][ii] = ee;
        });
    });
    var headerOutput = "";
    var seperatorOutput = "";
    maxRowLen.forEach(function (len) {
        var sizer = Array(len + 1 + 2);
        seperatorOutput += "|" + sizer.join("-");
        headerOutput += "|" + sizer.join(" ");
    });
    headerOutput += "| \n";
    seperatorOutput += "| \n";
    if (hasHeader) {
        headerOutput = "";
    }
    var rowOutput = "";
    tabularData.forEach(function (col, i) {
        maxRowLen.forEach(function (len, y) {
            var row = typeof col[y] == "undefined" ? "" : col[y];
            var spacing = Array((len - row.length) + 1).join(" ");
            var out = "| " + row + spacing + " ";
            if (hasHeader && i === 0) {
                headerOutput += out;
            }
            else {
                rowOutput += out;
            }
        });
        if (hasHeader && i === 0) {
            headerOutput += "| \n";
        }
        else {
            rowOutput += "| \n";
        }
    });
    return headerOutput + seperatorOutput + rowOutput;
}
if (typeof module != "undefined") {
    module.exports = csvToMarkdown;
}
<|endoftext|>


<commit_before>
"use strict";

var User = require('./User');
var Channel = require('./Channel');

var EventEmitter = require('events').EventEmitter;

var MumbleWrapper = function(connection) {
    this._users = {}; //Collect high-level information about users
    this._channels = {}; //Collect high-level information about channels
    this.sessions = {}; //Sessions to user map

    //TODO: We are storing the users twice to avoid some looping. Is this the
    //best approach?
    this.ready = false;
    this.connection = connection;
    this.rootChannel = undefined;
    this.user = undefined;
    this._gotServerSync;
    this._gotPermissionQuery;

    // Generate list of free whisper target IDs.
    this.freeTargets = [];
    for( var i = 1; i <= 30; i++ ) {
        this.freeTargets.push( i );
    }

    /*
     * Forward all events from the connection
     */
    this.on('newListener', function (event, listener) {
        connection.on(event, listener);
    });

    connection.on('permissionQuery', this._permissionQuery.bind( this ) );
    connection.on('serverSync', this._serverSync.bind( this ) );
    connection.on('userState', this._userState.bind( this ) );
    connection.on('channelState', this._channelState.bind( this ) );
    connection.on('textMessage', this._textMessage.bind( this ) );
};

MumbleWrapper.prototype = Object.create( EventEmitter.prototype );

MumbleWrapper.prototype._checkReady = function() {
    if(this._gotPermissionQuery && this._gotServerSync) {
        this.ready = true;
        this.emit('ready');
    }
};

MumbleWrapper.prototype._permissionQuery = function(data) {
    //TODO: Do something with the data
    this._gotPermissionQuery = true;
    this._checkReady();
};

MumbleWrapper.prototype._serverSync = function(data) {
    this.session = data.session;
    this.maxBandwidth = data.maxBandwidth;
    this.user = this.sessions[this.session];
    this._gotServerSync = true;
    this._checkReady();
    //Is really everything ready when we receive this?
    //TODO: Is this a good idea?
};

MumbleWrapper.prototype._textMessage = function(data) {
    var actor = this.sessions[data.actor];
    if(actor !== undefined) {
        if(data.session !== undefined) { // Then it was a private text message
            this.emit('message', data.message, actor, 'private');
        }
        else if(data.channelId !== undefined) { // A message to the channel
            this.emit('message', data.message, actor, 'channel');
        }
    }
};

MumbleWrapper.prototype._newUser = function(data) {
    var user = new User(data, this);

    this._wrapEvents( user, 'user', [
        'move', 'mute', 'self-mute', 'self-deaf', 'suppress',
        'recording', 'priority-speaker' ] );

    if(this.ready) {
        this.emit('user-connected', user);
    }
    return user;
};

MumbleWrapper.prototype._newChannel = function(data) {
    var channel = new Channel(data, this);
    if(channel.id === 0) {
        this.rootChannel = channel;
    }

    this._wrapEvents( channel, 'channel', [
        'rename', 'links-add', 'links-remove', 'move' ] );

    if(this.ready) {
        this.emit('channel-created', channel);
    }
    return channel;
};

/**
 * Wraps source events to be emitted from the Wrapper as well.
 *
 * @param {Object} source - Original event source
 * @param {String} prefix - Event prefix for the events the source emits.
 * @param {String[]} events - Events to delegate.
 */
MumbleWrapper.prototype._wrapEvents = function( source, prefix, events ) {
    var self = this;

    // Process all events
    events.forEach( function( event ) {
        var myEvent = prefix + '-' + event;
        source.on( event, function() {

            // Construct the event arguments for the 'emit' call:
            // eventName, source, ...original arguments
            var args = Array.prototype.slice.call( arguments );
            args.unshift( source );
            args.unshift( myEvent );

            // Emit.
            self.emit.apply( self, args );
        });
    });
};

MumbleWrapper.prototype._channelState = function(data) {
    if(this._channels[data.channelId] === undefined) {
        this._channels[data.channelId] = this._newChannel(data);
    }
    else {
        var channel = this._channels[data.channelId];
        channel.update(data);
    }
};

MumbleWrapper.prototype._userState = function(data) {
    if(this.sessions[data.session] === undefined) {
        var user = this._newUser(data);
        this._users[data.userId] = user;
        this.sessions[data.session] = user;
    }
    else {
        this.sessions[data.session].update( data );
    }
};

MumbleWrapper.prototype.users = function() {
    var list = [];
    for(var key in this._users) {
        list.push(this._users[key]);
    }
    return list;
};

MumbleWrapper.prototype.channelById = function(id) {
    return this._channels[id];
};

MumbleWrapper.prototype.userById = function(id) {
    return this._users[id];
};

MumbleWrapper.prototype.channelByName = function(name) {
    for(var key in this._channels) {
        var channel = this._channels[key];
        if(channel.name === name) {
            return channel;
        }
    }
    //Else return undefined
};

MumbleWrapper.prototype.userByName = function(name) {
    for(var key in this._users) {
        var user = this._users[key];
        if(user.name === name) {
            return user;
        }
    }
    //Else return undefined
};

/**
 * Allocates an input stream for a specific user session
 *
 * @param {Number|Array} sessionId - Single user session ID or an array of those.
 */
MumbleWrapper.prototype.inputStreamForUser = function( sessionId ) {
    var self = this;

    // If we got no free target IDs left, return null.
    if( this.freeTargets.length === 0 ) {
        return null;
    }

    // Create the targets parameter based on the sessionId type.
    var targets = [];
    if( typeof sessionId === 'number' ) {
        targets.push({ session: [ sessionId ] });
    } else {
        targets.push({ session: sessionId });
    }

    var whisperId = this.freeTargets.shift();

    this.sendMessage( 'VoiceTarget', {
        targets: targets,
        id: whisperId
    });

    var inputStream = this.connection.inputStream( whisperId );

    // Return the whisper ID to the target pool when we close the stream.
    inputStream.on( 'finish', function() {
        self.freeTargets.push( whisperId );
    });

    return inputStream;
};

/*
 * Forward all relevant methods from the connection
 */
MumbleWrapper.prototype.authenticate = function(name, password) {
    return this.connection.authenticate(name, password); };
MumbleWrapper.prototype.sendMessage = function(type, data) {
    return this.connection.sendMessage(type, data); };
MumbleWrapper.prototype.outputStream = function(userid) {
    return this.connection.outputStream(userid); };
MumbleWrapper.prototype.inputStream = function() {
    return this.connection.inputStream(); };
MumbleWrapper.prototype.joinPath = function(path) {
    return this.connection.joinPath(path); };
MumbleWrapper.prototype.sendVoice = function(chunk) {
    return this.connection.sendVoice(chunk); };
MumbleWrapper.prototype.disconnect = function() {
    return this.connection.disconnect(); };

module.exports = MumbleWrapper;
<commit_msg>Dont call ready twice.<commit_after>
"use strict";

var User = require('./User');
var Channel = require('./Channel');

var EventEmitter = require('events').EventEmitter;

var MumbleWrapper = function(connection) {
    this._users = {}; //Collect high-level information about users
    this._channels = {}; //Collect high-level information about channels
    this.sessions = {}; //Sessions to user map

    //TODO: We are storing the users twice to avoid some looping. Is this the
    //best approach?
    this.ready = false;
    this.connection = connection;
    this.rootChannel = undefined;
    this.user = undefined;
    this._gotServerSync;
    this._gotPermissionQuery;

    // Generate list of free whisper target IDs.
    this.freeTargets = [];
    for( var i = 1; i <= 30; i++ ) {
        this.freeTargets.push( i );
    }

    /*
     * Forward all events from the connection
     */
    this.on('newListener', function (event, listener) {
        connection.on(event, listener);
    });

    connection.on('permissionQuery', this._permissionQuery.bind( this ) );
    connection.on('serverSync', this._serverSync.bind( this ) );
    connection.on('userState', this._userState.bind( this ) );
    connection.on('channelState', this._channelState.bind( this ) );
    connection.on('textMessage', this._textMessage.bind( this ) );
};

MumbleWrapper.prototype = Object.create( EventEmitter.prototype );

MumbleWrapper.prototype._checkReady = function() {
    if(this._gotPermissionQuery && this._gotServerSync && !this.ready) {
        this.ready = true;
        this.emit('ready');
    }
};

MumbleWrapper.prototype._permissionQuery = function(data) {
    //TODO: Do something with the data
    this._gotPermissionQuery = true;
    this._checkReady();
};

MumbleWrapper.prototype._serverSync = function(data) {
    this.session = data.session;
    this.maxBandwidth = data.maxBandwidth;
    this.user = this.sessions[this.session];
    this._gotServerSync = true;
    this._checkReady();
    //Is really everything ready when we receive this?
    //TODO: Is this a good idea?
};

MumbleWrapper.prototype._textMessage = function(data) {
    var actor = this.sessions[data.actor];
    if(actor !== undefined) {
        if(data.session !== undefined) { // Then it was a private text message
            this.emit('message', data.message, actor, 'private');
        }
        else if(data.channelId !== undefined) { // A message to the channel
            this.emit('message', data.message, actor, 'channel');
        }
    }
};

MumbleWrapper.prototype._newUser = function(data) {
    var user = new User(data, this);

    this._wrapEvents( user, 'user', [
        'move', 'mute', 'self-mute', 'self-deaf', 'suppress',
        'recording', 'priority-speaker' ] );

    if(this.ready) {
        this.emit('user-connected', user);
    }
    return user;
};

MumbleWrapper.prototype._newChannel = function(data) {
    var channel = new Channel(data, this);
    if(channel.id === 0) {
        this.rootChannel = channel;
    }

    this._wrapEvents( channel, 'channel', [
        'rename', 'links-add', 'links-remove', 'move' ] );

    if(this.ready) {
        this.emit('channel-created', channel);
    }
    return channel;
};

/**
 * Wraps source events to be emitted from the Wrapper as well.
 *
 * @param {Object} source - Original event source
 * @param {String} prefix - Event prefix for the events the source emits.
 * @param {String[]} events - Events to delegate.
 */
MumbleWrapper.prototype._wrapEvents = function( source, prefix, events ) {
    var self = this;

    // Process all events
    events.forEach( function( event ) {
        var myEvent = prefix + '-' + event;
        source.on( event, function() {

            // Construct the event arguments for the 'emit' call:
            // eventName, source, ...original arguments
            var args = Array.prototype.slice.call( arguments );
            args.unshift( source );
            args.unshift( myEvent );

            // Emit.
            self.emit.apply( self, args );
        });
    });
};

MumbleWrapper.prototype._channelState = function(data) {
    if(this._channels[data.channelId] === undefined) {
        this._channels[data.channelId] = this._newChannel(data);
    }
    else {
        var channel = this._channels[data.channelId];
        channel.update(data);
    }
};

MumbleWrapper.prototype._userState = function(data) {
    if(this.sessions[data.session] === undefined) {
        var user = this._newUser(data);
        this._users[data.userId] = user;
        this.sessions[data.session] = user;
    }
    else {
        this.sessions[data.session].update( data );
    }
};

MumbleWrapper.prototype.users = function() {
    var list = [];
    for(var key in this._users) {
        list.push(this._users[key]);
    }
    return list;
};

MumbleWrapper.prototype.channelById = function(id) {
    return this._channels[id];
};

MumbleWrapper.prototype.userById = function(id) {
    return this._users[id];
};

MumbleWrapper.prototype.channelByName = function(name) {
    for(var key in this._channels) {
        var channel = this._channels[key];
        if(channel.name === name) {
            return channel;
        }
    }
    //Else return undefined
};

MumbleWrapper.prototype.userByName = function(name) {
    for(var key in this._users) {
        var user = this._users[key];
        if(user.name === name) {
            return user;
        }
    }
    //Else return undefined
};

/**
 * Allocates an input stream for a specific user session
 *
 * @param {Number|Array} sessionId - Single user session ID or an array of those.
 */
MumbleWrapper.prototype.inputStreamForUser = function( sessionId ) {
    var self = this;

    // If we got no free target IDs left, return null.
    if( this.freeTargets.length === 0 ) {
        return null;
    }

    // Create the targets parameter based on the sessionId type.
    var targets = [];
    if( typeof sessionId === 'number' ) {
        targets.push({ session: [ sessionId ] });
    } else {
        targets.push({ session: sessionId });
    }

    var whisperId = this.freeTargets.shift();

    this.sendMessage( 'VoiceTarget', {
        targets: targets,
        id: whisperId
    });

    var inputStream = this.connection.inputStream( whisperId );

    // Return the whisper ID to the target pool when we close the stream.
    inputStream.on( 'finish', function() {
        self.freeTargets.push( whisperId );
    });

    return inputStream;
};

/*
 * Forward all relevant methods from the connection
 */
MumbleWrapper.prototype.authenticate = function(name, password) {
    return this.connection.authenticate(name, password); };
MumbleWrapper.prototype.sendMessage = function(type, data) {
    return this.connection.sendMessage(type, data); };
MumbleWrapper.prototype.outputStream = function(userid) {
    return this.connection.outputStream(userid); };
MumbleWrapper.prototype.inputStream = function() {
    return this.connection.inputStream(); };
MumbleWrapper.prototype.joinPath = function(path) {
    return this.connection.joinPath(path); };
MumbleWrapper.prototype.sendVoice = function(chunk) {
    return this.connection.sendVoice(chunk); };
MumbleWrapper.prototype.disconnect = function() {
    return this.connection.disconnect(); };

module.exports = MumbleWrapper;
<|endoftext|>