<commit_before>'use strict';

/* Controllers */

function MainCtrl($scope) {
  $scope.logoState = '';
  $scope.$on('$routeChangeSuccess', function() {
    $scope.logoState = '';
  });
  $scope.$on('unanimous vote', function() {
    $scope.logoState = 'green';
  });
  $scope.$on('not unanimous vote', function() {
    $scope.logoState = 'yellow';
  });
  $scope.$on('problem vote', function() {
    $scope.logoState = 'red';
  });
  $scope.$on('unfinished vote', function() {
    $scope.logoState = '';
  });
}

MainCtrl.$inject = ['$scope'];

function LobbyCtrl($scope, $location, socketService) {
  $scope.createRoom = function() {
    // console.log('createRoom: emit create room');
    socketService.emit('create room', {}, function(roomUrl){
      $scope.$apply(function() {
        $location.path(roomUrl);
      });
    });
  }
  $scope.enterRoom = function(room) {
    // console.log('enterRoom: room info');
    socketService.emit('room info', { roomUrl: room }, function(response){
      $scope.$apply(function() {
        if (response.error) {
          $scope.errorMessage = response.error;
          $timeout(function() {
            $scope.errorMessage = null;
          }, 3000);
        } else {
          // console.log("going to enter room " + response.roomUrl);
          $location.path(response.roomUrl);
        }
      });
    });
  }
}

LobbyCtrl.$inject = ['$scope', '$location', 'socketService'];

function RoomCtrl($scope, $routeParams, $timeout, socketService) {

  var processMessage = function(response, process) {
    // console.log("processMessage: response:", response)
    if (response.error) {
      $scope.$apply(function() {
        $scope.errorMessage = response.error;
        $timeout(function() {
          $scope.errorMessage = null;
        }, 3000);
      });
    } else {
      $scope.$apply(function() {
        $scope.errorMessage = null;
      });
      (process || angular.noop)(response);
    }
  };

  var displayMessage = function(msg) {
    $scope.$apply(function() {
      $scope.message = msg;
      $timeout(function() {
        $scope.message = null;
      }, 5000);
    });
  }

  // wipe out vote if voting state is not yet finished to prevent cheating.
  // if it has already been set - use the actual vote. This works for unvoting - so that
  // before the flip occurs - we don't display 'oi'
  var processVotes = function() {
    var voteCount = $scope.votes.length;
    _.each($scope.votes, function(v) {
      v.visibleVote = v.visibleVote === undefined && voteCount < $scope.voterCount ? 'oi!' : v.vote;
    });

    if ($scope.votes.length == $scope.voterCount) {
      var uniqVotes = _.chain($scope.votes).pluck('vote').uniq().value().length;
      if (uniqVotes == 1) {
        $scope.$emit('unanimous vote');
      } else if (uniqVotes == $scope.voterCount) {
        $scope.$emit('problem vote');
      } else if ($scope.voterCount > 3 && uniqVotes == ($scope.voterCount - 1)) {
        $scope.$emit('problem vote');
      } else {
        $scope.$emit('not unanimous vote');
      }
    } else {
      $scope.$emit('unfinished vote');
    }
  }

  var myConnectionHash = function() {
    return _.find($scope.connections, function(c) { return c.sessionId == $scope.sessionId });
  }

  var myVoteHash = function() {
    return _.find($scope.votes, function(c) { return c.sessionId == $scope.sessionId });
  }

  var setLocalVote = function(vote) {
    $scope.myVote = vote;
    var voteHash = myVoteHash();
    if (!voteHash) {
      // initialize connections array with my first vote. (just to speed up UI)
      $scope.votes.push({ sessionId: $scope.sessionId, vote: vote });
    } else {
      if (vote) {
        voteHash.vote = vote;
      } else {
        // we're unvoting - lets remove it from the votes.
        $scope.votes = _.filter($scope.votes, function(v) { return v.sessionId != $scope.sessionId } );
        // the above works - but causes an error in the UI.
      }
    }
    processVotes();
    $scope.votingState = $scope.votes.length == $scope.voterCount ? 'finished' : ''
  }

  var refreshRoomInfo = function(roomObj) {
    // console.log("refreshRoomInfo: roomObj:", roomObj)
    $scope.$apply(function() {
      if (roomObj.createAdmin) {
        $.cookie("admin-" + roomObj.roomUrl, true);
      }
      if($.cookie("admin-" + roomObj.roomUrl)) {
        $scope.showAdmin = true;
      }

      $scope.humanCount = roomObj.clientCount;
      $scope.cardPack = roomObj.cardPack;

      if ($scope.cardPack == 'fib') {
        $scope.cards = ['0', '1', '2', '3', '5', '8', '13', '21', '34', '55', '89', '?'];
      } else if ($scope.cardPack == 'goat') {
        $scope.cards = ['0', '\u00BD', '1', '2', '3', '5', '8', '13', '20', '40', '100', '?', '\u2615'];
      } else if ($scope.cardPack == 'seq') {
        $scope.cards = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '?'];
      } else if ($scope.cardPack == 'play') {
        $scope.cards = ['A\u2660', '2', '3', '5', '8', '\u2654'];
      } else if ($scope.cardPack == 'tshirt') {
        $scope.cards = ['XL', 'L', 'M', 'S', 'XS', '?'];
      }
      $scope.connections = _.filter(roomObj.connections, function(c) { return c.socketId });
      $scope.votes = _.chain($scope.connections).filter(function(c) { return c.vote }).values().value();
      $scope.voterCount = _.filter($scope.connections, function(c) { return c.voter }).length;

      var connection = myConnectionHash();

      if (connection) {
        $scope.voter = connection.voter;
        $scope.myVote = connection.vote;
      }

      processVotes();

    });

    // we first want the cards to be displayed as hidden, and then apply the finished state
    // if voting has finished - which then actions the transition.
    $timeout(function() {
      $scope.votingState = $scope.votes.length == $scope.voterCount ? 'finished' : '';
    }, 100);

  }

  $scope.configureRoom = function() {

    socketService.on('room joined', function () {
      // console.log("on room joined");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('room left', function () {
      // console.log("on room left");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('card pack set', function () {
      displayMessage('Card pack changed...' + );
      // console.log("on card pack set");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('voter status changed', function () {
      // console.log("on voter status changed");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('voted', function () {
      // console.log("on voted");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('unvoted', function () {
      // console.log("on unvoted");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('vote reset', function () {
      // console.log("on vote reset");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('connect', function() {
      // console.log("on connect");
      var sessionId = this.socket.sessionid;
      // console.log("new socket id = " + sessionId);
      if (!$.cookie("sessionId")) {
        $.cookie("sessionId", sessionId);
      }
      $scope.$apply(function() {
        $scope.sessionId = $.cookie("sessionId");
        // console.log("session id = " + $scope.sessionId);
      });
      // console.log("emit join room", { roomUrl: $scope.roomId, sessionId: $scope.sessionId });
      socketService.emit('join room', { roomUrl: $scope.roomId, sessionId: $scope.sessionId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('disconnect', function() {
      // console.log("on disconnect");
    });

    // console.log("emit join room", { roomUrl: $scope.roomId, sessionId: $scope.sessionId });
    socketService.emit('join room', { roomUrl: $scope.roomId, sessionId: $scope.sessionId }, function(response){
      processMessage(response, refreshRoomInfo);
    });
  }

  $scope.setCardPack = function(cardPack) {
    $scope.cardPack = cardPack;
    $scope.resetVote();

    // console.log("set card pack", { roomUrl: $scope.roomId, cardPack: cardPack });
    socketService.emit('set card pack', { roomUrl: $scope.roomId, cardPack: cardPack });
  }

  $scope.vote = function(vote) {
    if ($scope.myVote != vote) {

      setLocalVote(vote);

      // console.log("emit vote", { roomUrl: $scope.roomId, vote: vote, sessionId: $scope.sessionId });
      socketService.emit('vote', { roomUrl: $scope.roomId, vote: vote, sessionId: $scope.sessionId }, function(response) {
        processMessage(response);
      });
    }
  }

  $scope.unvote = function(sessionId) {
    if (sessionId == $scope.sessionId) {

      setLocalVote(null);

      // console.log("emit unvote", { roomUrl: $scope.roomId, sessionId: $scope.sessionId });
      socketService.emit('unvote', { roomUrl: $scope.roomId, sessionId: $scope.sessionId }, function(response) {
        processMessage(response);
      });
    }
  }

  $scope.resetVote = function() {
    // console.log("emit reset vote", { roomUrl: $scope.roomId });
    socketService.emit('reset vote', { roomUrl: $scope.roomId }, function(response) {
      processMessage(response);
    });
  }

  $scope.toggleVoter = function() {
    // console.log("emit toggle voter", { roomUrl: $scope.roomId, voter: $scope.voter, sessionId: $scope.sessionId });
    socketService.emit('toggle voter', { roomUrl: $scope.roomId, voter: $scope.voter, sessionId: $scope.sessionId }, function(response) {
      processMessage(response);
    });
  }

  $scope.roomId = $routeParams.roomId;
  $scope.humanCount = 0;
  $scope.voterCount = 0;
  $scope.showAdmin = false;
  $scope.voter = true;
  $scope.errorMessage = null;
  $scope.message = null;
  $scope.connections = {};
  $scope.votes = [];
  $scope.cardPack = '';
  $scope.myVote = null;
  $scope.votingState = "";
}

RoomCtrl.$inject = ['$scope', '$routeParams', '$timeout', 'socketService'];<commit_msg>Oh goodness!<commit_after>'use strict';

/* Controllers */

function MainCtrl($scope) {
  $scope.logoState = '';
  $scope.$on('$routeChangeSuccess', function() {
    $scope.logoState = '';
  });
  $scope.$on('unanimous vote', function() {
    $scope.logoState = 'green';
  });
  $scope.$on('not unanimous vote', function() {
    $scope.logoState = 'yellow';
  });
  $scope.$on('problem vote', function() {
    $scope.logoState = 'red';
  });
  $scope.$on('unfinished vote', function() {
    $scope.logoState = '';
  });
}

MainCtrl.$inject = ['$scope'];

function LobbyCtrl($scope, $location, socketService) {
  $scope.createRoom = function() {
    // console.log('createRoom: emit create room');
    socketService.emit('create room', {}, function(roomUrl){
      $scope.$apply(function() {
        $location.path(roomUrl);
      });
    });
  }
  $scope.enterRoom = function(room) {
    // console.log('enterRoom: room info');
    socketService.emit('room info', { roomUrl: room }, function(response){
      $scope.$apply(function() {
        if (response.error) {
          $scope.errorMessage = response.error;
          $timeout(function() {
            $scope.errorMessage = null;
          }, 3000);
        } else {
          // console.log("going to enter room " + response.roomUrl);
          $location.path(response.roomUrl);
        }
      });
    });
  }
}

LobbyCtrl.$inject = ['$scope', '$location', 'socketService'];

function RoomCtrl($scope, $routeParams, $timeout, socketService) {

  var processMessage = function(response, process) {
    // console.log("processMessage: response:", response)
    if (response.error) {
      $scope.$apply(function() {
        $scope.errorMessage = response.error;
        $timeout(function() {
          $scope.errorMessage = null;
        }, 3000);
      });
    } else {
      $scope.$apply(function() {
        $scope.errorMessage = null;
      });
      (process || angular.noop)(response);
    }
  };

  var displayMessage = function(msg) {
    $scope.$apply(function() {
      $scope.message = msg;
      $timeout(function() {
        $scope.message = null;
      }, 5000);
    });
  }

  // wipe out vote if voting state is not yet finished to prevent cheating.
  // if it has already been set - use the actual vote. This works for unvoting - so that
  // before the flip occurs - we don't display 'oi'
  var processVotes = function() {
    var voteCount = $scope.votes.length;
    _.each($scope.votes, function(v) {
      v.visibleVote = v.visibleVote === undefined && voteCount < $scope.voterCount ? 'oi!' : v.vote;
    });

    if ($scope.votes.length == $scope.voterCount) {
      var uniqVotes = _.chain($scope.votes).pluck('vote').uniq().value().length;
      if (uniqVotes == 1) {
        $scope.$emit('unanimous vote');
      } else if (uniqVotes == $scope.voterCount) {
        $scope.$emit('problem vote');
      } else if ($scope.voterCount > 3 && uniqVotes == ($scope.voterCount - 1)) {
        $scope.$emit('problem vote');
      } else {
        $scope.$emit('not unanimous vote');
      }
    } else {
      $scope.$emit('unfinished vote');
    }
  }

  var myConnectionHash = function() {
    return _.find($scope.connections, function(c) { return c.sessionId == $scope.sessionId });
  }

  var myVoteHash = function() {
    return _.find($scope.votes, function(c) { return c.sessionId == $scope.sessionId });
  }

  var setLocalVote = function(vote) {
    $scope.myVote = vote;
    var voteHash = myVoteHash();
    if (!voteHash) {
      // initialize connections array with my first vote. (just to speed up UI)
      $scope.votes.push({ sessionId: $scope.sessionId, vote: vote });
    } else {
      if (vote) {
        voteHash.vote = vote;
      } else {
        // we're unvoting - lets remove it from the votes.
        $scope.votes = _.filter($scope.votes, function(v) { return v.sessionId != $scope.sessionId } );
        // the above works - but causes an error in the UI.
      }
    }
    processVotes();
    $scope.votingState = $scope.votes.length == $scope.voterCount ? 'finished' : ''
  }

  var refreshRoomInfo = function(roomObj) {
    // console.log("refreshRoomInfo: roomObj:", roomObj)
    $scope.$apply(function() {
      if (roomObj.createAdmin) {
        $.cookie("admin-" + roomObj.roomUrl, true);
      }
      if($.cookie("admin-" + roomObj.roomUrl)) {
        $scope.showAdmin = true;
      }

      $scope.humanCount = roomObj.clientCount;
      $scope.cardPack = roomObj.cardPack;

      if ($scope.cardPack == 'fib') {
        $scope.cards = ['0', '1', '2', '3', '5', '8', '13', '21', '34', '55', '89', '?'];
      } else if ($scope.cardPack == 'goat') {
        $scope.cards = ['0', '\u00BD', '1', '2', '3', '5', '8', '13', '20', '40', '100', '?', '\u2615'];
      } else if ($scope.cardPack == 'seq') {
        $scope.cards = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '?'];
      } else if ($scope.cardPack == 'play') {
        $scope.cards = ['A\u2660', '2', '3', '5', '8', '\u2654'];
      } else if ($scope.cardPack == 'tshirt') {
        $scope.cards = ['XL', 'L', 'M', 'S', 'XS', '?'];
      }
      $scope.connections = _.filter(roomObj.connections, function(c) { return c.socketId });
      $scope.votes = _.chain($scope.connections).filter(function(c) { return c.vote }).values().value();
      $scope.voterCount = _.filter($scope.connections, function(c) { return c.voter }).length;

      var connection = myConnectionHash();

      if (connection) {
        $scope.voter = connection.voter;
        $scope.myVote = connection.vote;
      }

      processVotes();

    });

    // we first want the cards to be displayed as hidden, and then apply the finished state
    // if voting has finished - which then actions the transition.
    $timeout(function() {
      $scope.votingState = $scope.votes.length == $scope.voterCount ? 'finished' : '';
    }, 100);

  }

  $scope.configureRoom = function() {

    socketService.on('room joined', function () {
      // console.log("on room joined");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('room left', function () {
      // console.log("on room left");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('card pack set', function () {
      displayMessage('Card pack changed...');
      // console.log("on card pack set");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('voter status changed', function () {
      // console.log("on voter status changed");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('voted', function () {
      // console.log("on voted");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('unvoted', function () {
      // console.log("on unvoted");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('vote reset', function () {
      // console.log("on vote reset");
      // console.log("emit room info", { roomUrl: $scope.roomId });
      this.emit('room info', { roomUrl: $scope.roomId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('connect', function() {
      // console.log("on connect");
      var sessionId = this.socket.sessionid;
      // console.log("new socket id = " + sessionId);
      if (!$.cookie("sessionId")) {
        $.cookie("sessionId", sessionId);
      }
      $scope.$apply(function() {
        $scope.sessionId = $.cookie("sessionId");
        // console.log("session id = " + $scope.sessionId);
      });
      // console.log("emit join room", { roomUrl: $scope.roomId, sessionId: $scope.sessionId });
      socketService.emit('join room', { roomUrl: $scope.roomId, sessionId: $scope.sessionId }, function(response){
        processMessage(response, refreshRoomInfo);
      });
    });
    socketService.on('disconnect', function() {
      // console.log("on disconnect");
    });

    // console.log("emit join room", { roomUrl: $scope.roomId, sessionId: $scope.sessionId });
    socketService.emit('join room', { roomUrl: $scope.roomId, sessionId: $scope.sessionId }, function(response){
      processMessage(response, refreshRoomInfo);
    });
  }

  $scope.setCardPack = function(cardPack) {
    $scope.cardPack = cardPack;
    $scope.resetVote();

    // console.log("set card pack", { roomUrl: $scope.roomId, cardPack: cardPack });
    socketService.emit('set card pack', { roomUrl: $scope.roomId, cardPack: cardPack });
  }

  $scope.vote = function(vote) {
    if ($scope.myVote != vote) {

      setLocalVote(vote);

      // console.log("emit vote", { roomUrl: $scope.roomId, vote: vote, sessionId: $scope.sessionId });
      socketService.emit('vote', { roomUrl: $scope.roomId, vote: vote, sessionId: $scope.sessionId }, function(response) {
        processMessage(response);
      });
    }
  }

  $scope.unvote = function(sessionId) {
    if (sessionId == $scope.sessionId) {

      setLocalVote(null);

      // console.log("emit unvote", { roomUrl: $scope.roomId, sessionId: $scope.sessionId });
      socketService.emit('unvote', { roomUrl: $scope.roomId, sessionId: $scope.sessionId }, function(response) {
        processMessage(response);
      });
    }
  }

  $scope.resetVote = function() {
    // console.log("emit reset vote", { roomUrl: $scope.roomId });
    socketService.emit('reset vote', { roomUrl: $scope.roomId }, function(response) {
      processMessage(response);
    });
  }

  $scope.toggleVoter = function() {
    // console.log("emit toggle voter", { roomUrl: $scope.roomId, voter: $scope.voter, sessionId: $scope.sessionId });
    socketService.emit('toggle voter', { roomUrl: $scope.roomId, voter: $scope.voter, sessionId: $scope.sessionId }, function(response) {
      processMessage(response);
    });
  }

  $scope.roomId = $routeParams.roomId;
  $scope.humanCount = 0;
  $scope.voterCount = 0;
  $scope.showAdmin = false;
  $scope.voter = true;
  $scope.errorMessage = null;
  $scope.message = null;
  $scope.connections = {};
  $scope.votes = [];
  $scope.cardPack = '';
  $scope.myVote = null;
  $scope.votingState = "";
}

RoomCtrl.$inject = ['$scope', '$routeParams', '$timeout', 'socketService'];<|endoftext|>


<commit_before>/* ncapratings.js */

var app = {
    API_BASE_URL: 'http://www.nhtsa.gov/webapi/api/SafetyRatings/',
    API_BASE_PARAMS: 'format=json',
    API_JSONP_CALLBACK: 'callback',
    selectedManufacturer: '',

    initialize: function() {
        app.displayModelYears();
    },

    displayModelYears: function() {
        $.ajax({
            cache: false,
            dataType: 'jsonp',
            error: function(xhr, status, errorMsg) {
                app.showGeneralError('Failed to load model year data!');
            },
            jsonp: app.API_JSONP_CALLBACK,
            method: 'GET',
            success: app.onModelYearsLoaded,
            url: app.API_BASE_URL + '?' + app.API_BASE_PARAMS
        });
    },

    onModelYearsLoaded: function(data, status) {
        var n = 0,
            modelYear,
            htmlStr = ''
                + '
'
                + '
'
                + '
Select Model Year
'
                + '
';

        if (data && data.Results) {
            for (; n < data.Results.length; n++) {
                modelYear = data.Results[n].ModelYear;
                htmlStr += '
' + modelYear + '
';
            }
        }

        htmlStr = htmlStr
            + '
'
            + '
'
            + '
';

        $('#pageContent').html(htmlStr);

        $('#modelYears li').click(function(e) {
                app.onModelYearSelected($(this).attr('id'));
        });
    },

    onModelYearSelected: function(modelYear) {
        $.ajax({
            cache: false,
            dataType: 'jsonp',
            error: function(xhr, status, errorMsg) {
                app.showGeneralError('Failed to load manufacturers for model year ' + modelYear + '!');
            },
            jsonp: app.API_JSONP_CALLBACK,
            method: 'GET',
            success: app.onManufacturersLoaded,
            url: app.API_BASE_URL + '/modelyear/' + modelYear + '?' + app.API_BASE_PARAMS
        });
    },

    onManufacturersLoaded: function(data, status) {
        var n = 0,
            manufacturer = '',
            modelYear,
            htmlStr = '';

        if (data && data.Results) {
            $('#navButtons').show();

            modelYear = data.Results[0].ModelYear;

            htmlStr += ''
                + '
'
                + '
'
                + '
' + modelYear + '
'
                + '
';

            for (; n < data.Results.length; n++) {
                manufacturer = data.Results[n].Make;
                htmlStr += '
' + manufacturer + '
';
            }

            htmlStr = htmlStr
                + '
'
                + '
'
                + '
';
        }

        $('#pageContent').html(htmlStr);
        $('#manufacturers li').click(function(e) {
                app.onManufacturerSelected($(this).attr('id'), modelYear);
        });
    },

    onManufacturerSelected: function(manufacturer, modelYear) {
        $.ajax({
            cache: false,
            dataType: 'jsonp',
            error: function(xhr, status, errorMsg) {
                app.showGeneralError('Failed to load vehicle models for manufacturer ' + manufacturer + '!');
            },
            jsonp: app.API_JSONP_CALLBACK,
            method: 'GET',
            success: app.onModelsLoaded,
            url: app.API_BASE_URL + 'modelyear/' + modelYear + '/make/' + manufacturer + '?' + app.API_BASE_PARAMS
        });
    },

    onModelsLoaded: function(data, status) {
        var n = 0,
            manufacturer = '',
            modelYear,
            htmlStr = '';

        if (data && data.Results) {
            modelYear = data.Results[0].ModelYear;
            manufacturer = data.Results[0].Make;

            htmlStr += ''
                + '
'
                + '
'
                + '
' + modelYear + ' ' + manufacturer + '
'
                + '
';

            for (; n < data.Results.length; n++) {
                vehicle = data.Results[n].Model;
                htmlStr += '
' + vehicle + '
';
            }

            htmlStr = htmlStr
                + '
'
                + '
'
                + '
';
        }

        $('#pageContent').html(htmlStr);
        $('#vehicles li').click(function(e) {
                app.onVehicleSelected($(this).attr('id'), modelYear, manufacturer);
        });
    },

    onVehicleSelected: function(vehicle, modelYear, manufacturer) {
        $.ajax({
            cache: false,
            dataType: 'jsonp',
            error: function(xhr, status, errorMsg) {
                app.showGeneralError('Failed to load vehicle ' + vehicle + '!');
            },
            jsonp: app.API_JSONP_CALLBACK,
            method: 'GET',
            success: app.onVehicleLoaded,
            url: app.API_BASE_URL + 'modelyear/' + modelYear + '/make/' + manufacturer + '/model/' + vehicle + '?' + app.API_BASE_PARAMS
        });
    },

    onVehicleLoaded: function(data, status) {
        var vehicleId = '';

        // Nothing to display yet as we have to use VehicleId from data
        // to get details...

        if (data && data.Results) {
            vehicleId = data.Results[0].VehicleId;

            $.ajax({
                cache: false,
                dataType: 'jsonp',
                error: function(xhr, status, errorMsg) {
                    app.showGeneralError('Failed to load vehicle details for ' + data.Results[0].VehicleDescription);
                },
                jsonp: app.API_JSONP_CALLBACK,
                method: 'GET',
                success: app.onVehicleDetailLoaded,
                url: app.API_BASE_URL + 'VehicleId/' + vehicleId + '?' + app.API_BASE_PARAMS
            });
        }
    },

    onVehicleDetailLoaded: function(data, status) {
        var vehicleDetails = undefined,
            numRecalls = 0,
            htmlStr = '';

        if (data && data.Results && data.Results.length === 1) {
            vehicleDetails = data.Results[0];

            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
' + vehicleDetails.ModelYear + ' ' + vehicleDetails.Make + ' ' + vehicleDetails.Model + '
';
            htmlStr += '
';
            htmlStr += '
';

            if (vehicleDetails.VehiclePicture) {
                htmlStr += '
';
                htmlStr += '
';
                htmlStr += '    ';
                htmlStr += '
';
                htmlStr += '
';
            }

            htmlStr += '
';

            // Star Ratings

            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
Star Ratings
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Overall	' + app.generateStarRating(vehicleDetails.OverallRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Front Crash	' + app.generateStarRating(vehicleDetails.OverallFrontCrashRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Side Crash	' + app.generateStarRating(vehicleDetails.OverallSideCrashRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Side Pole Crash	' + app.generateStarRating(vehicleDetails.SidePoleCrashRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Rollover	' + app.generateStarRating(vehicleDetails.RolloverRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';

            // Images

            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
Crash Test Pictures
';
            htmlStr += '
';
            htmlStr += '
';
            if (vehicleDetails.FrontCrashPicture) {
                htmlStr += '';
            } else {
                htmlStr += '
Front crash image unavailable.
';
            }

            if (vehicleDetails.SideCrashPicture) {
                htmlStr += '';
            } else {
                htmlStr += '
Side crash image unavailable.
';
            }

            if (vehicleDetails.SidePolePicture) {
                htmlStr += '';
            } else {
                htmlStr += '
Side pole crash image unavailable.
';
            }

            htmlStr += '
';
            htmlStr += '
';
            // Recalls
            numRecalls = vehicleDetails.RecallsCount;

            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
Recalls
';
            htmlStr += '
';
            htmlStr += '
';

            switch(numRecalls) {
                case 0:
                    htmlStr += '
There are no known recalls affecting this vehicle.
';
                    break;
                case 1:
                    htmlStr += '
This vehicle is subject to 1 recall.
';
                    break;
                default:
                    htmlStr += '
This vehicle is subject to ' + numRecalls + ' recalls.
';
            }

            htmlStr += '
';
            htmlStr += '
';
        }

        $('#pageContent').html(htmlStr);
    },

    generateStarRating(numStars) {
        var n = 0,
            htmlStars = '';

        if (numStars === 'Not Rated') {
            return numStars;
        }

        for (; n < numStars; n++) {
            htmlStars += '';
        }

        return htmlStars;
    },

    showGeneralError(errorMsg) {
        alert(errorMsg);
    }
}

window.onload = function() {
  app.initialize();
};<commit_msg>Added missing level of list for car model that Dave noticed.<commit_after>/* ncapratings.js */

var app = {
    API_BASE_URL: 'http://www.nhtsa.gov/webapi/api/SafetyRatings/',
    API_BASE_PARAMS: 'format=json',
    API_JSONP_CALLBACK: 'callback',
    selectedManufacturer: '',

    initialize: function() {
        app.displayModelYears();
    },

    displayModelYears: function() {
        $.ajax({
            cache: false,
            dataType: 'jsonp',
            error: function(xhr, status, errorMsg) {
                app.showGeneralError('Failed to load model year data!');
            },
            jsonp: app.API_JSONP_CALLBACK,
            method: 'GET',
            success: app.onModelYearsLoaded,
            url: app.API_BASE_URL + '?' + app.API_BASE_PARAMS
        });
    },

    onModelYearsLoaded: function(data, status) {
        var n = 0,
            modelYear,
            htmlStr = ''
                + '
'
                + '
'
                + '
Select Model Year
'
                + '
';

        if (data && data.Results) {
            for (; n < data.Results.length; n++) {
                modelYear = data.Results[n].ModelYear;
                htmlStr += '
' + modelYear + '
';
            }
        }

        htmlStr = htmlStr
            + '
'
            + '
'
            + '
';

        $('#pageContent').html(htmlStr);

        $('#modelYears li').click(function(e) {
                app.onModelYearSelected($(this).attr('id'));
        });
    },

    onModelYearSelected: function(modelYear) {
        $.ajax({
            cache: false,
            dataType: 'jsonp',
            error: function(xhr, status, errorMsg) {
                app.showGeneralError('Failed to load manufacturers for model year ' + modelYear + '!');
            },
            jsonp: app.API_JSONP_CALLBACK,
            method: 'GET',
            success: app.onManufacturersLoaded,
            url: app.API_BASE_URL + '/modelyear/' + modelYear + '?' + app.API_BASE_PARAMS
        });
    },

    onManufacturersLoaded: function(data, status) {
        var n = 0,
            manufacturer = '',
            modelYear,
            htmlStr = '';

        if (data && data.Results) {
            $('#navButtons').show();

            modelYear = data.Results[0].ModelYear;

            htmlStr += ''
                + '
'
                + '
'
                + '
' + modelYear + '
'
                + '
';

            for (; n < data.Results.length; n++) {
                manufacturer = data.Results[n].Make;
                htmlStr += '
' + manufacturer + '
';
            }

            htmlStr = htmlStr
                + '
'
                + '
'
                + '
';
        }

        $('#pageContent').html(htmlStr);
        $('#manufacturers li').click(function(e) {
                app.onManufacturerSelected($(this).attr('id'), modelYear);
        });
    },

    onManufacturerSelected: function(manufacturer, modelYear) {
        $.ajax({
            cache: false,
            dataType: 'jsonp',
            error: function(xhr, status, errorMsg) {
                app.showGeneralError('Failed to load vehicle models for manufacturer ' + manufacturer + '!');
            },
            jsonp: app.API_JSONP_CALLBACK,
            method: 'GET',
            success: app.onModelsLoaded,
            url: app.API_BASE_URL + 'modelyear/' + modelYear + '/make/' + manufacturer + '?' + app.API_BASE_PARAMS
        });
    },

    onModelsLoaded: function(data, status) {
        var n = 0,
            manufacturer = '',
            modelYear,
            htmlStr = '';

        if (data && data.Results) {
            modelYear = data.Results[0].ModelYear;
            manufacturer = data.Results[0].Make;

            htmlStr += ''
                + '
'
                + '
'
                + '
' + modelYear + ' ' + manufacturer + '
'
                + '
';

            for (; n < data.Results.length; n++) {
                vehicle = data.Results[n].Model;
                htmlStr += '
' + vehicle + '
';
            }

            htmlStr = htmlStr
                + '
'
                + '
'
                + '
';
        }

        $('#pageContent').html(htmlStr);
        $('#vehicles li').click(function(e) {
                app.onVehicleModelSelected($(this).attr('id'), modelYear, manufacturer);
        });
    },

    onVehicleModelSelected: function(vehicle, modelYear, manufacturer) {
        $.ajax({
            cache: false,
            dataType: 'jsonp',
            error: function(xhr, status, errorMsg) {
                app.showGeneralError('Failed to load vehicle model ' + vehicle + '!');
            },
            jsonp: app.API_JSONP_CALLBACK,
            manufacturer: manufacturer,
            method: 'GET',
            model: vehicle,
            modelYear: modelYear,
            success: app.onVehiclesLoaded,
            url: app.API_BASE_URL + 'modelyear/' + modelYear + '/make/' + manufacturer + '/model/' + vehicle + '?' + app.API_BASE_PARAMS
        });
    },

    onVehiclesLoaded: function(data, status) {
        var n = 0,
            htmlStr = '',
            vehicle;

        if (data && data.Results) {
            htmlStr += ''
                + '
'
                + '
'
                + '
' + this.modelYear + ' ' + this.manufacturer + ' ' + this.model + '
'
                + '
';

            for (; n < data.Results.length; n++) {
                vehicle = data.Results[n];
                htmlStr += '
' + vehicle.VehicleDescription + '
';
            }

            htmlStr = htmlStr
                + '
'
                + '
'
                + '
';
        }

        $('#pageContent').html(htmlStr);
        $('#vehicles li').click(function(e) {
            app.onVehicleIdSelected($(this).attr('id'));
        });
    },

    onVehicleIdSelected: function(vehicleId) {
        $.ajax({
            cache: false,
            dataType: 'jsonp',
            error: function(xhr, status, errorMsg) {
                app.showGeneralError('Failed to load vehicle details for ' + data.Results[0].VehicleDescription);
            },
            jsonp: app.API_JSONP_CALLBACK,
            method: 'GET',
            success: app.onVehicleDetailLoaded,
            url: app.API_BASE_URL + 'VehicleId/' + vehicleId + '?' + app.API_BASE_PARAMS
        });
    },

    onVehicleDetailLoaded: function(data, status) {
        var vehicleDetails = undefined,
            numRecalls = 0,
            htmlStr = '';

        if (data && data.Results && data.Results.length === 1) {
            vehicleDetails = data.Results[0];

            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
' + vehicleDetails.VehicleDescription + '
';
            htmlStr += '
';
            htmlStr += '
';

            if (vehicleDetails.VehiclePicture) {
                htmlStr += '
';
                htmlStr += '
';
                htmlStr += '    ';
                htmlStr += '
';
                htmlStr += '
';
            }

            htmlStr += '
';

            // Star Ratings

            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
Star Ratings
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Overall	' + app.generateStarRating(vehicleDetails.OverallRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Front Crash	' + app.generateStarRating(vehicleDetails.OverallFrontCrashRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Side Crash	' + app.generateStarRating(vehicleDetails.OverallSideCrashRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Side Pole Crash	' + app.generateStarRating(vehicleDetails.SidePoleCrashRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '          Rollover	' + app.generateStarRating(vehicleDetails.RolloverRating) + '	';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
';

            // Images

            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
Crash Test Pictures
';
            htmlStr += '
';
            htmlStr += '
';
            if (vehicleDetails.FrontCrashPicture) {
                htmlStr += '';
            } else {
                htmlStr += '
Front crash image unavailable.
';
            }

            if (vehicleDetails.SideCrashPicture) {
                htmlStr += '';
            } else {
                htmlStr += '
Side crash image unavailable.
';
            }

            if (vehicleDetails.SidePolePicture) {
                htmlStr += '';
            } else {
                htmlStr += '
Side pole crash image unavailable.
';
            }

            htmlStr += '
';
            htmlStr += '
';
            // Recalls
            numRecalls = vehicleDetails.RecallsCount;

            htmlStr += '
';
            htmlStr += '
';
            htmlStr += '
Recalls
';
            htmlStr += '
';
            htmlStr += '
';

            switch(numRecalls) {
                case 0:
                    htmlStr += '
There are no known recalls affecting this vehicle.
';
                    break;
                case 1:
                    htmlStr += '
This vehicle is subject to 1 recall.
';
                    break;
                default:
                    htmlStr += '
This vehicle is subject to ' + numRecalls + ' recalls.
';
            }

            htmlStr += '
';
            htmlStr += '
';
        }

        $('#pageContent').html(htmlStr);
    },

    generateStarRating(numStars) {
        var n = 0,
            htmlStars = '';

        if (numStars === 'Not Rated') {
            return numStars;
        }

        for (; n < numStars; n++) {
            htmlStars += '';
        }

        return htmlStars;
    },

    showGeneralError(errorMsg) {
        alert(errorMsg);
    }
}

window.onload = function() {
  app.initialize();
};<|endoftext|>


<commit_before>const material = `
  body {
  	font-family: 'Roboto';
  	font-size: 13px;
  	color: #212121;
  	background-color: #fafafa;
  	line-height: 1.846;
  }

  h1,h2,h3,h4,h5,h6 {
  	font-weight: 400;
  	line-height: 1.2;
  }

  h1 {
  	font-size: 6em;
  	font-weight: 300;
  	margin-bottom: 0.6em;
  	color: #039be5;
  	line-height: 1.17;
  	letter-spacing: -0.03em;
  }

  h2 {
  	font-size: 2.61em;
  	font-weight: 400;
  	margin-top: 1.2em;
  	margin-bottom: 0.83em;
  	color: #039be5;
  	line-height: 1.17;
  }

  h3 {
  	font-size: 1.84em;
  	font-weight: 400;
  	margin-top: 2em;
  	margin-bottom: 1.25em;
  	color: #039be5;
  	line-height: 1.33;
  }

  h4 {
  	font-size: 1.5em;
  	font-weight: 400;
  	margin-top: 2em;
  	margin-bottom: 1.5em;
  	line-height: 1.6;
  }

  h5 {
  	font-size: 1.23em;
  	font-weight: 500;
  	margin-top: 3em;
  	margin-bottom: 1.875em;
  	line-height: 1.5;
  }

  h6 {
  	font-size: 1.15em;
  	font-weight: 500;
  	margin-top: 3em;
  	margin-bottom: 1.5em;
  	font-family: 'Roboto';
  	line-height: 1.6;
  }

  p {
  	margin-bottom: 1.53em;
  }

  strong {
  	font-weight: 700;
  }

  em {
  	font-style: italic;
  }

  a {
  	color: #039be5;
  	text-decoration: none;
  }

  ul,ol {
  	margin-top: 1em;
  	margin-bottom: 1.5em;
  	padding-left: 1.1em;
  }

  li {
  	margin-top: 0.5em;
  	margin-bottom: 0.75em;
  }

}`;

export default material;
<commit_msg>WIP Typo on styles<commit_after>const material = `{
  body {
  	font-family: 'Roboto';
  	font-size: 13px;
  	color: #212121;
  	background-color: #fafafa;
  	line-height: 1.846;
  }

  h1,h2,h3,h4,h5,h6 {
  	font-weight: 400;
  	line-height: 1.2;
  }

  h1 {
  	font-size: 6em;
  	font-weight: 300;
  	margin-bottom: 0.6em;
  	color: #039be5;
  	line-height: 1.17;
  	letter-spacing: -0.03em;
  }

  h2 {
  	font-size: 2.61em;
  	font-weight: 400;
  	margin-top: 1.2em;
  	margin-bottom: 0.83em;
  	color: #039be5;
  	line-height: 1.17;
  }

  h3 {
  	font-size: 1.84em;
  	font-weight: 400;
  	margin-top: 2em;
  	margin-bottom: 1.25em;
  	color: #039be5;
  	line-height: 1.33;
  }

  h4 {
  	font-size: 1.5em;
  	font-weight: 400;
  	margin-top: 2em;
  	margin-bottom: 1.5em;
  	line-height: 1.6;
  }

  h5 {
  	font-size: 1.23em;
  	font-weight: 500;
  	margin-top: 3em;
  	margin-bottom: 1.875em;
  	line-height: 1.5;
  }

  h6 {
  	font-size: 1.15em;
  	font-weight: 500;
  	margin-top: 3em;
  	margin-bottom: 1.5em;
  	font-family: 'Roboto';
  	line-height: 1.6;
  }

  p {
  	margin-bottom: 1.53em;
  }

  strong {
  	font-weight: 700;
  }

  em {
  	font-style: italic;
  }

  a {
  	color: #039be5;
  	text-decoration: none;
  }

  ul,ol {
  	margin-top: 1em;
  	margin-bottom: 1.5em;
  	padding-left: 1.1em;
  }

  li {
  	margin-top: 0.5em;
  	margin-bottom: 0.75em;
  }

}`;

export default material;
<|endoftext|>


<commit_before>'use strict'

import d3 from 'd3'
import jquery from 'jquery-deferred'

module.exports = function(dataPath, color) {
  var deferred = jquery.Deferred();

  d3.tsv(dataPath, function(error, cityData) {
    if (error) throw error;

    // define the domain
    color.domain(["TOTAL"]);

    // Remove the data with no organization name for the moment
    var cityData = cityData.filter(function(d) {
      return d.ORGANIZATION !== '';
    });

    // console.log(JSON.stringify(cityData, null, 2));

    // aggregate by department/ORGANIZATION
    // TODO: similar division names for:
    // IG-Office of Inspector GenDept division IG-Inspector General is repeated
    // CL-Council Services division CL-Council Svcs is repeated
    // filter them out is a possibility (after "divisions:"))
    // d.filter(function(el, i, arr) {
    //   if(i > 0) {
    //     return el.DIVISION == arr[i-1].DIVISION ? false : true;
    //   } else {
    //     return true;
    //   }
    // })
    var cityData = d3.nest()
    .key(function(d) { return d.ORGANIZATION.replace(/Department|Dept|DP/gi, '');})
    .rollup(function(d) {
        return {
          total: d3.sum(d, function(g) { return g.TOTAL; }),
          divisions: d.map(function(g) {
           return {
             name: g.DIVISION,
             description: g.ACCOUNT_DESCRIPTION,
             total: g.TOTAL
           }
         })
        }
      })
    .entries(cityData);

    // calculate the city's full annual budget
    var cityBudget = 0;
    for (var i = 0, l = cityData.length; i < l; i++) {
      cityBudget += parseFloat(cityData[i].values.total);
    }

    // calculate relative values
    for (var i = 0, l = cityData.length; i < l; i++) {
      var d = cityData[i];
      d.values.budgets = [
        {
          name: 'total',
          amount: +d.values.total
        },
        {
          name: 'remainder',
          amount: cityBudget - d.values.total
        }
      ];
      d.values.percentage = d.values.total / cityBudget;
    }

    console.log(JSON.stringify(cityData, null, 2));

    // resolve the promise and pass the data
    deferred.resolve(cityData, cityBudget);
  });

  return deferred.promise();
};
<commit_msg>data ready to be displayed properly in department single view<commit_after>'use strict'

import d3 from 'd3'
import jquery from 'jquery-deferred'

module.exports = function(dataPath, color) {
  var deferred = jquery.Deferred();

  d3.tsv(dataPath, function(error, cityData) {
    if (error) throw error;

    // define the domain
    color.domain(["TOTAL"]);

    // Remove the data with no organization name for the moment
    var cityData = cityData.filter(function(d) {
      return d.ORGANIZATION !== '';
    });

    // aggregate by department/ORGANIZATION
    var cityData = d3.nest()
    .key(function(d) { return d.ORGANIZATION.replace(/Department|Dept|DP/gi, '');})
    .rollup(function(d) {
      return {
        total: d3.sum(d, function(g) { return g.TOTAL; }),
        divisions: d.map(function(g, i, arr) {
          var obj = {
           name: g.DIVISION,
           description: g.ACCOUNT_DESCRIPTION,
           total: g.TOTAL
          };

          if(i < arr.length-1) {
            obj.showDescription = g.DIVISION == arr[i+1].DIVISION ? true : false;
          } else {
            obj.showDescription = g.DIVISION == arr[i-1].DIVISION ? true : false;
          }
          return obj;
        })
      };
    })
    .entries(cityData);

    // calculate the city's full annual budget
    var cityBudget = 0;
    for (var i = 0, l = cityData.length; i < l; i++) {
      cityBudget += parseFloat(cityData[i].values.total);
    }

    // calculate relative values
    for (var i = 0, l = cityData.length; i < l; i++) {
      var d = cityData[i];
      d.values.budgets = [
      {
        name: 'total',
        amount: +d.values.total
      },
      {
        name: 'remainder',
        amount: cityBudget - d.values.total
      }
      ];
      d.values.percentage = d.values.total / cityBudget;
    }

    console.log(JSON.stringify(cityData, null, 2));

    // resolve the promise and pass the data
    deferred.resolve(cityData, cityBudget);
  });

return deferred.promise();

};
<|endoftext|>


<commit_before>module.exports=function(leaflet){

};<commit_msg>Removed old file<commit_after><|endoftext|>


<commit_before>// Example model

module.exports = function (sequelize, DataTypes) {

  var Article = sequelize.define('Article', {
    title: DataTypes.STRING,
    url: DataTypes.STRING,
    text: DataTypes.STRING
  }, {
    classMethods: {
      associate: function (models) {
        // example on how to add relations
        // Article.hasMany(models.Comments);
      }
    }
  });

  return Article;
};

<commit_msg>remove example model<commit_after><|endoftext|>


<commit_before>import _ from 'lodash'
import GraphemeBreaker from 'grapheme-breaker'

import { PubSub as pubSub } from '../models'

export function addModel(dbAdapter) {
  /**
   * @constructor
   */
  const Comment = function (params) {
    this.id = params.id
    this.body = params.body
    this.userId = params.userId
    this.postId = params.postId
    if (parseInt(params.createdAt, 10))
      this.createdAt = params.createdAt
    if (parseInt(params.updatedAt, 10))
      this.updatedAt = params.updatedAt
  }

  Comment.className = Comment
  Comment.namespace = 'comment'

  Object.defineProperty(Comment.prototype, 'body', {
    get: function () { return this.body_ },
    set: function (newValue) {
      newValue ? this.body_ = newValue.trim() : this.body_ = ''
    }
  })

  Comment.prototype.validate = async function() {
    const valid = this.body
               && this.body.length > 0
               && this.userId
               && this.userId.length > 0
               && this.postId
               && this.postId.length > 0

    if (!valid) {
      throw new Error('Comment text must not be empty')
    }

    const len = GraphemeBreaker.countBreaks(this.body)

    if (len > 1500) {
      throw new Error('Maximum comment length is 1500 characters')
    }
  }

  Comment.prototype.create = async function() {
    this.createdAt = new Date().getTime()
    this.updatedAt = new Date().getTime()

    await this.validate()

    const payload = {
      'body':      this.body,
      'userId':    this.userId,
      'postId':    this.postId,
      'createdAt': this.createdAt.toString(),
      'updatedAt': this.updatedAt.toString()
    }

    this.id = await dbAdapter.createComment(payload)

    const post = await dbAdapter.getPostById(this.postId)
    const timelines = await post.addComment(this)

    await dbAdapter.statsCommentCreated(this.userId)

    return timelines
  }

  Comment.prototype.update = async function(params) {
    this.updatedAt = new Date().getTime()
    this.body = params.body

    await this.validate()

    const payload = {
      'body':      this.body,
      'updatedAt': this.updatedAt.toString()
    }
    await dbAdapter.updateComment(this.id, payload)

    await pubSub.updateComment(this.id)

    return this
  }

  Comment.prototype.getPost = function () {
    return dbAdapter.getPostById(this.postId)
  }

  Comment.prototype.destroy = async function() {
    await dbAdapter.deleteComment(this.id, this.postId)

    // look for comment from this user in this post
    // if this is was the last one remove this post from user's comments timeline
    const post = await dbAdapter.getPostById(this.postId)
    const comments = await post.getComments()

    if (_.some(comments, ['userId', this.userId])) {
      return
    }

    const user = await dbAdapter.getUserById(this.userId)
    const timelineId = await user.getCommentsTimelineIntId()

    await dbAdapter.withdrawPostFromFeeds([timelineId], this.postId)

    await dbAdapter.statsCommentDeleted(this.userId)
    await pubSub.destroyComment(this.id, this.postId)
  }

  Comment.prototype.getCreatedBy = function () {
    return dbAdapter.getUserById(this.userId)
  }

  return Comment
}
<commit_msg>Implement hashtag autocreating and auto(un)linking on comment create/update.<commit_after>import _ from 'lodash'
import GraphemeBreaker from 'grapheme-breaker'
import twitter from 'twitter-text'

import { PubSub as pubSub } from '../models'

export function addModel(dbAdapter) {
  /**
   * @constructor
   */
  const Comment = function (params) {
    this.id = params.id
    this.body = params.body
    this.userId = params.userId
    this.postId = params.postId
    if (parseInt(params.createdAt, 10))
      this.createdAt = params.createdAt
    if (parseInt(params.updatedAt, 10))
      this.updatedAt = params.updatedAt
  }

  Comment.className = Comment
  Comment.namespace = 'comment'

  Object.defineProperty(Comment.prototype, 'body', {
    get: function () { return this.body_ },
    set: function (newValue) {
      newValue ? this.body_ = newValue.trim() : this.body_ = ''
    }
  })

  Comment.prototype.validate = async function() {
    const valid = this.body
               && this.body.length > 0
               && this.userId
               && this.userId.length > 0
               && this.postId
               && this.postId.length > 0

    if (!valid) {
      throw new Error('Comment text must not be empty')
    }

    const len = GraphemeBreaker.countBreaks(this.body)

    if (len > 1500) {
      throw new Error('Maximum comment length is 1500 characters')
    }
  }

  Comment.prototype.create = async function() {
    this.createdAt = new Date().getTime()
    this.updatedAt = new Date().getTime()

    await this.validate()

    const payload = {
      'body':      this.body,
      'userId':    this.userId,
      'postId':    this.postId,
      'createdAt': this.createdAt.toString(),
      'updatedAt': this.updatedAt.toString()
    }

    this.id = await dbAdapter.createComment(payload)

    const post = await dbAdapter.getPostById(this.postId)
    const timelines = await post.addComment(this)

    await this.processHashtagsOnCreate()

    await dbAdapter.statsCommentCreated(this.userId)

    return timelines
  }

  Comment.prototype.update = async function(params) {
    this.updatedAt = new Date().getTime()
    this.body = params.body

    await this.validate()

    const payload = {
      'body':      this.body,
      'updatedAt': this.updatedAt.toString()
    }
    await dbAdapter.updateComment(this.id, payload)

    await this.processHashtagsOnUpdate()

    await pubSub.updateComment(this.id)

    return this
  }

  Comment.prototype.getPost = function () {
    return dbAdapter.getPostById(this.postId)
  }

  Comment.prototype.destroy = async function() {
    await dbAdapter.deleteComment(this.id, this.postId)

    // look for comment from this user in this post
    // if this is was the last one remove this post from user's comments timeline
    const post = await dbAdapter.getPostById(this.postId)
    const comments = await post.getComments()

    if (_.some(comments, ['userId', this.userId])) {
      return
    }

    const user = await dbAdapter.getUserById(this.userId)
    const timelineId = await user.getCommentsTimelineIntId()

    await dbAdapter.withdrawPostFromFeeds([timelineId], this.postId)

    await dbAdapter.statsCommentDeleted(this.userId)
    await pubSub.destroyComment(this.id, this.postId)
  }

  Comment.prototype.getCreatedBy = function () {
    return dbAdapter.getUserById(this.userId)
  }

  Comment.prototype.processHashtagsOnCreate = async function () {
    const commentTags = _.uniq(twitter.extractHashtags(this.body))

    if (!commentTags || commentTags.length == 0) {
      return
    }
    await dbAdapter.linkCommentHashtagsByNames(commentTags, this.id)
  }

  Comment.prototype.processHashtagsOnUpdate = async function () {
    const linkedCommentHashtags = await dbAdapter.getCommentHashtags(this.id)

    const presentTags    = _.sortBy(linkedCommentHashtags.map((t) => t.name))
    const newTags        = _.sortBy(_.uniq(twitter.extractHashtags(this.body)))
    const notChangedTags = _.intersection(presentTags, newTags)
    const tagsToUnlink   = _.difference(presentTags, notChangedTags)
    const tagsToLink     = _.difference(newTags, notChangedTags)

    if (presentTags != newTags) {
      if (tagsToUnlink.length > 0) {
        await dbAdapter.unlinkCommentHashtagsByNames(tagsToUnlink, this.id)
      }
      if (tagsToLink.length > 0) {
        await dbAdapter.linkCommentHashtagsByNames(tagsToLink, this.id)
      }
    }
  }

  return Comment
}
<|endoftext|>


<commit_before>"use strict";

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

let pokemon = {
    pokemonId: Number,
    name: {type: String},
    icon: {type: String},
    classification: {type: String},
    types: [String],
    resistance: [String],
    weakness: [String],
    fastAttacks: [{name: {type: String}, type: {type: String}, damage: {type: Number}}],
    specialAttacks: [{name: {type: String}, type: {type: String}, damage: {type: Number}}],
    weight: {
        minimum: {type: String},
        maximum: {type: String}
    },
    height: {
        minimum: {type: String},
        maximum: {type: String}
    },
    fleeRate: Number,
    nextEvolutions: [{pokemonId: Number, name: {type: String}}],
    previousEvolutions: [{pokemonId: Number, name: {type: String}}],
    maxCP: Number,
    maxHP: Number,
    gender: {
        abbreviation: {
            type: String, enum: ['m', 'f', 'g', 'h'] //m=male, f=female, g=genderless, h=hermaphrodite
        },
        maleRatio: Number,
        femaleRatio: Number,
        breedable: Boolean
    }
};

var pokemonGoBasicSchema = new Schema(pokemon);

pokemonGoBasicSchema.index({"pokemonId": 1}, {"unique": true});

module.exports = {

    getModel: function () {
        return pokemon;
    },
    getSchema: function () {
        return mongoose.model('pokemon', pokemonGoBasicSchema);
    },
    getMappedModel: function (pokemon) {
        let attack_type_expr, attack_name_expr, attack_damage_expr;
        let search_by = [];

        if (pokemon.attackType) {
            attack_type_expr = new RegExp('^' + pokemon.attackType + '$', 'i');
            search_by.push({$or: [{"fastAttacks.type": attack_type_expr}, {"specialAttacks.type": attack_type_expr}]});
        }
        if (pokemon.attackName) {
            attack_name_expr = new RegExp('^' + pokemon.attackName + '$', 'i');
            search_by.push({$or: [{"fastAttacks.name": attack_name_expr}, {"specialAttacks.name": attack_name_expr}]});
        }

        if (pokemon.minAttackDamage) {
            attack_damage_expr = {};
            attack_damage_expr["$gte"] = pokemon.minAttackDamage;
        }
        if (pokemon.maxAttackDamage) {
            attack_damage_expr = attack_damage_expr || {};
            attack_damage_expr["$lt"] = pokemon.maxAttackDamage;
        }

        if (attack_damage_expr) {
            search_by.push({$or: [{"fastAttacks.damage": attack_damage_expr},
                {"specialAttacks.damage": attack_damage_expr}
            ]});
        }

        if (pokemon.evolution) {
            search_by.push({$or: [{"nextEvolutions.pokemonId": pokemon.evolution},
                {"previousEvolutions.pokemonId": pokemon.evolution}
            ]});
        }

        let mappedModel = {
            "pokemonId": pokemon.id || pokemon.pokemonId,
            "name": pokemon.name,
            "icon": pokemon.icon,
            "classification": pokemon.classification,
            "types": pokemon.type && pokemon.type.toLowerCase(),
            "resistance": pokemon.resistance && pokemon.resistance.toLowerCase(),
            "weakness": pokemon.weakness && pokemon.weakness.toLowerCase(),
            "weight.minimum": pokemon.minWeight,
            "weight.maximum": pokemon.maxWeight,
            "height.minimum": pokemon.minHeight,
            "height.maximum": pokemon.maxHeight,
            "fleeRate": pokemon.fleeRate,
            "maxCP": pokemon.maxCP,
            "maxHP": pokemon.maxHP,
            "gender.abbreviation": pokemon.gender && pokemon.gender.toLowerCase()
        };

        if (search_by.length > 1) {
            mappedModel["$and"] = search_by
        } else if (search_by.length === 1) {
            mappedModel["$or"] = search_by[0]["$or"];
        }

        return mappedModel;
    }
};<commit_msg>search api - return results where query is contained in the name, not only exact match<commit_after>"use strict";

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

let pokemon = {
    pokemonId: Number,
    name: {type: String},
    icon: {type: String},
    classification: {type: String},
    types: [String],
    resistance: [String],
    weakness: [String],
    fastAttacks: [{name: {type: String}, type: {type: String}, damage: {type: Number}}],
    specialAttacks: [{name: {type: String}, type: {type: String}, damage: {type: Number}}],
    weight: {
        minimum: {type: String},
        maximum: {type: String}
    },
    height: {
        minimum: {type: String},
        maximum: {type: String}
    },
    fleeRate: Number,
    nextEvolutions: [{pokemonId: Number, name: {type: String}}],
    previousEvolutions: [{pokemonId: Number, name: {type: String}}],
    maxCP: Number,
    maxHP: Number,
    gender: {
        abbreviation: {
            type: String, enum: ['m', 'f', 'g', 'h'] //m=male, f=female, g=genderless, h=hermaphrodite
        },
        maleRatio: Number,
        femaleRatio: Number,
        breedable: Boolean
    }
};

var pokemonGoBasicSchema = new Schema(pokemon);

pokemonGoBasicSchema.index({"pokemonId": 1}, {"unique": true});

module.exports = {

    getModel: function () {
        return pokemon;
    },
    getSchema: function () {
        return mongoose.model('pokemon', pokemonGoBasicSchema);
    },
    getMappedModel: function (pokemon) {
        let attack_type_expr, attack_name_expr, attack_damage_expr;
        let search_by = [];

        if (pokemon.attackType) {
            attack_type_expr = new RegExp('^' + pokemon.attackType + '$', 'i');
            search_by.push({$or: [{"fastAttacks.type": attack_type_expr}, {"specialAttacks.type": attack_type_expr}]});
        }
        if (pokemon.attackName) {
            attack_name_expr = new RegExp('^' + pokemon.attackName + '$', 'i');
            search_by.push({$or: [{"fastAttacks.name": attack_name_expr}, {"specialAttacks.name": attack_name_expr}]});
        }

        if (pokemon.minAttackDamage) {
            attack_damage_expr = {};
            attack_damage_expr["$gte"] = pokemon.minAttackDamage;
        }
        if (pokemon.maxAttackDamage) {
            attack_damage_expr = attack_damage_expr || {};
            attack_damage_expr["$lt"] = pokemon.maxAttackDamage;
        }

        if (attack_damage_expr) {
            search_by.push({$or: [{"fastAttacks.damage": attack_damage_expr},
                {"specialAttacks.damage": attack_damage_expr}
            ]});
        }

        if (pokemon.evolution) {
            search_by.push({$or: [{"nextEvolutions.pokemonId": pokemon.evolution},
                {"previousEvolutions.pokemonId": pokemon.evolution}
            ]});
        }

        let mappedModel = {
            "pokemonId": pokemon.id || pokemon.pokemonId,
            "name": new RegExp('^.*' + pokemon.name + '.*$', 'i'),
            "icon": pokemon.icon,
            "classification": pokemon.classification,
            "types": pokemon.type && pokemon.type.toLowerCase(),
            "resistance": pokemon.resistance && pokemon.resistance.toLowerCase(),
            "weakness": pokemon.weakness && pokemon.weakness.toLowerCase(),
            "weight.minimum": pokemon.minWeight,
            "weight.maximum": pokemon.maxWeight,
            "height.minimum": pokemon.minHeight,
            "height.maximum": pokemon.maxHeight,
            "fleeRate": pokemon.fleeRate,
            "maxCP": pokemon.maxCP,
            "maxHP": pokemon.maxHP,
            "gender.abbreviation": pokemon.gender && pokemon.gender.toLowerCase()
        };

        if (search_by.length > 1) {
            mappedModel["$and"] = search_by
        } else if (search_by.length === 1) {
            mappedModel["$or"] = search_by[0]["$or"];
        }

        return mappedModel;
    }
};<|endoftext|>


<commit_before>import { spawn } from 'child_process';

function replacePlaceholders(string, params) {
    return string.replace(/\{\{([a-z0-9_]+)\}\}/ig, (match, key) => {
        if (!params[key] || !params[key].length) {
            throw 'exec: "' + key + '" is missing or empty';
        }
        return params[key];
    });
}

export default async (command, params, stdin, env = {}) => {
    return new Promise((resolve, reject) => {
        let commandParts = command.split(/ +/).map(part => {
            return replacePlaceholders(part, params)
        });
        let result = '';
        let error = '';
        let child = spawn(commandParts[0], commandParts.slice(1), {
            env: {
                ...process.env,
                ...env
            }
        });
        child.on('error', reject);
        child.stderr.on('data', data => error += data);
        child.stdout.on('data', data => result += data);
        child.on('exit', code => {
            if (code === 0) {
                resolve(result);
            } else {
                let err = new Error('Code has been exited with code ' + code);
                err.code = code;
                reject(err);
            }
        });
        if (stdin) {
            child.stdin.write(stdin + '\n');
            child.stdin.end();
        }
    });
};
<commit_msg>Updated error message<commit_after>import { spawn } from 'child_process';

function replacePlaceholders(string, params) {
    return string.replace(/\{\{([a-z0-9_]+)\}\}/ig, (match, key) => {
        if (!params[key] || !params[key].length) {
            throw 'exec: "' + key + '" is missing or empty';
        }
        return params[key];
    });
}

export default async (command, params, stdin, env = {}) => {
    return new Promise((resolve, reject) => {
        let commandParts = command.split(/ +/).map(part => {
            return replacePlaceholders(part, params)
        });
        let result = '';
        let error = '';
        let child = spawn(commandParts[0], commandParts.slice(1), {
            env: {
                ...process.env,
                ...env
            }
        });
        child.on('error', reject);
        child.stderr.on('data', data => error += data);
        child.stdout.on('data', data => result += data);
        child.on('exit', code => {
            if (code === 0) {
                resolve(result);
            } else {
                let err = new Error('Command exited with code ' + code);
                err.code = code;
                reject(err);
            }
        });
        if (stdin) {
            child.stdin.write(stdin + '\n');
            child.stdin.end();
        }
    });
};
<|endoftext|>


<commit_before>import * as Promise from 'bluebird'
import * as Immutable from 'immutable'
import * as _ from 'lodash'

import uuid from 'app/helpers/uuid'
import randomChar from 'app/helpers/randomChar'
import countCredits from 'app/helpers/countCredits'

import Schedule from 'app/models/schedule'
import Study from 'app/models/study'

import * as demoStudent from 'sto-areas/demo_student.json'

let currentVersionString = '3.0.0alpha8'

let StudentRecord = Immutable.Record({
	id: uuid(),
	name: 'Student ' + randomChar(),
	active: false,
	version: currentVersionString,

	creditsNeeded: 35,

	matriculation: 1894,
	graduation: 1898,

	studies: Immutable.Map(),
	schedules: Immutable.Map(),
	overrides: Immutable.Map(),
	fabrications: Immutable.Map(),

	settings: Immutable.Map(),
})

class Student extends StudentRecord {
	constructor(encodedStudent={}) {
		// Don't pass the list params into the StudentRecord constructor; it creates them as JS objects,
		// instead of our custom Studies, Schedules, and such.
		let toRemove = Immutable.Set(['studies', 'schedules', 'overrides', 'fabrications'])
		let filtered = Immutable.fromJS(encodedStudent).filterNot((val, key) => toRemove.has(key))

		super(filtered)

		// Then add them manually.
		if (encodedStudent) {
			return this.withMutations((student) => {
				Immutable.Seq(encodedStudent.studies || [])
					.forEach(study => { student = student.addArea(study) })

				Immutable.Seq(encodedStudent.schedules || [])
					.forEach(schedule => { student = student.addSchedule(schedule) })

				Immutable.Seq(encodedStudent.overrides || [])
					.forEach(override => { student = student.addOverride(override) })

				Immutable.Seq(encodedStudent.fabrications || [])
					.forEach(fabrication => { student = student.addFabrication(fabrication) })

				return student
			})
		}
	}

	changeName(newName) {
		return this.set('name', newName)
	}

	changeActive(isActive) {
		return this.set('active', isActive)
	}

	changeCreditsNeeded(newCreditsNeeded) {
		return this.set('creditsNeeded', newCreditsNeeded)
	}

	changeMatriculation(newMatriculation) {
		return this.set('matriculation', newMatriculation)
	}

	changeGraduation(newGraduation) {
		return this.set('graduation', newGraduation)
	}

	changeSetting(key, value) {
		return this.setIn(['settings', key], value)
	}

	// schedule methods

	get schedulesByYear() {
		return this.schedules.groupBy(sched => sched.year)
	}

	get activeSchedules() {
		return this.schedules.filter(sched => sched.active).sortBy(sched => sched.semester)
	}

	addSchedule(newSchedule) {
		let sched = new Schedule(newSchedule)
		return this.setIn(['schedules', sched.id], sched)
	}

	destroySchedule(scheduleId) {
		console.log(`removing schedule ${scheduleId}`)

		let deadSched = this.getIn(['schedules', scheduleId])
		let scheduleIsNoMore = this.set('schedules', this.schedules.delete(scheduleId))

		if (deadSched && deadSched.active) {
			let otherSchedKey = this.schedules.findKey((sched) =>
				sched.year === deadSched.year && sched.semester === deadSched.semester)

			if (otherSchedKey) {
				return scheduleIsNoMore.setIn(['schedules', otherSchedKey, 'active'], true)
			}
		}
		return scheduleIsNoMore
	}

	destroyMultipleSchedules(ids) {
		return this.withMutations((student) => {
			console.groupCollapsed('destroyMultipleSchedules')
			Immutable.Seq(ids).forEach((id) => {
				console.log('destroyMultipleSchedules', id)
				student = student.destroySchedule(id)
			})
			console.groupEnd('destroyMultipleSchedules')
			return student
		})
	}

	// area-of-study methods

	get areasByType() {
		return this.studies.groupBy((study) => study.type)
	}

	addArea(areaOfStudy) {
		let study = new Study(areaOfStudy)
		return this.setIn(['studies', study.id], study)
	}

	removeArea(id) {
		return this.set('studies', this.studies.delete(id))
	}

	removeMultipleAreas(ids) {
		Seq(ids).forEach(this.removeArea, this)
	}

	// override methods

	addOverride(override) {
		return this.setIn(['overrides', override.id], override)
	}

	removeOverride(overrideId) {
		return this.set('overrides', this.overrides.delete(overrideId))
	}

	// fabrication methods

	addFabrication(fabrication) {
		return this.setIn(['fabrications', fabrication.id], fabrication)
	}

	removeFabrication(fabricationId) {
		return this.set('fabrications', this.fabrications.delete(fabricationId))
	}

	// getters

	get courses() {
		let allCourses = this.activeSchedules.map((schedule) => schedule.courses).toArray()
		let scheduleCoursePromises = Promise.all(allCourses)
		return scheduleCoursePromises.then((results) => _.flatten(results))
	}

	get creditCount() {
		return this.courses.then(countCredits)
	}

	// helpers

	data() {
		return Promise.props({
			courses: this.courses,
			fabrications: this.fabrications.toArray(),
			overrides: this.overrides.toArray(),
			studies: this.studies.toArray(),
			creditsNeeded: this.creditsNeeded,
			graduation: this.graduation,
			matriculation: this.matriculation,
		})
	}

	encode() {
		return encodeURIComponent(this.toJS())
	}

	toString() {
		return JSON.stringify(this.toJS())
	}

	toJSON() {
		return JSON.stringify(this.toJS())
	}

	save() {
		console.log(`saving student ${this.name} (${this.id})`)
		localStorage.setItem(this.id, this.toJSON())

		if (this.active)
			localStorage.setItem('activeStudentId', this.id)
	}
}

export default Student
<commit_msg>Deeply convert student.fabrications, etc, to arrays<commit_after>import * as Promise from 'bluebird'
import * as Immutable from 'immutable'
import * as _ from 'lodash'

import uuid from 'app/helpers/uuid'
import randomChar from 'app/helpers/randomChar'
import countCredits from 'app/helpers/countCredits'

import Schedule from 'app/models/schedule'
import Study from 'app/models/study'

import * as demoStudent from 'sto-areas/demo_student.json'

let currentVersionString = '3.0.0alpha8'

let StudentRecord = Immutable.Record({
	id: uuid(),
	name: 'Student ' + randomChar(),
	active: false,
	version: currentVersionString,

	creditsNeeded: 35,

	matriculation: 1894,
	graduation: 1898,

	studies: Immutable.Map(),
	schedules: Immutable.Map(),
	overrides: Immutable.Map(),
	fabrications: Immutable.Map(),

	settings: Immutable.Map(),
})

class Student extends StudentRecord {
	constructor(encodedStudent={}) {
		// Don't pass the list params into the StudentRecord constructor; it creates them as JS objects,
		// instead of our custom Studies, Schedules, and such.
		let toRemove = Immutable.Set(['studies', 'schedules', 'overrides', 'fabrications'])
		let filtered = Immutable.fromJS(encodedStudent).filterNot((val, key) => toRemove.has(key))

		super(filtered)

		// Then add them manually.
		if (encodedStudent) {
			return this.withMutations((student) => {
				Immutable.Seq(encodedStudent.studies || [])
					.forEach(study => { student = student.addArea(study) })

				Immutable.Seq(encodedStudent.schedules || [])
					.forEach(schedule => { student = student.addSchedule(schedule) })

				Immutable.Seq(encodedStudent.overrides || [])
					.forEach(override => { student = student.addOverride(override) })

				Immutable.Seq(encodedStudent.fabrications || [])
					.forEach(fabrication => { student = student.addFabrication(fabrication) })

				return student
			})
		}
	}

	changeName(newName) {
		return this.set('name', newName)
	}

	changeActive(isActive) {
		return this.set('active', isActive)
	}

	changeCreditsNeeded(newCreditsNeeded) {
		return this.set('creditsNeeded', newCreditsNeeded)
	}

	changeMatriculation(newMatriculation) {
		return this.set('matriculation', newMatriculation)
	}

	changeGraduation(newGraduation) {
		return this.set('graduation', newGraduation)
	}

	changeSetting(key, value) {
		return this.setIn(['settings', key], value)
	}

	// schedule methods

	get schedulesByYear() {
		return this.schedules.groupBy(sched => sched.year)
	}

	get activeSchedules() {
		return this.schedules.filter(sched => sched.active).sortBy(sched => sched.semester)
	}

	addSchedule(newSchedule) {
		let sched = new Schedule(newSchedule)
		return this.setIn(['schedules', sched.id], sched)
	}

	destroySchedule(scheduleId) {
		console.log(`removing schedule ${scheduleId}`)

		let deadSched = this.getIn(['schedules', scheduleId])
		let scheduleIsNoMore = this.set('schedules', this.schedules.delete(scheduleId))

		if (deadSched && deadSched.active) {
			let otherSchedKey = this.schedules.findKey((sched) =>
				sched.year === deadSched.year && sched.semester === deadSched.semester)

			if (otherSchedKey) {
				return scheduleIsNoMore.setIn(['schedules', otherSchedKey, 'active'], true)
			}
		}
		return scheduleIsNoMore
	}

	destroyMultipleSchedules(ids) {
		return this.withMutations((student) => {
			console.groupCollapsed('destroyMultipleSchedules')
			Immutable.Seq(ids).forEach((id) => {
				console.log('destroyMultipleSchedules', id)
				student = student.destroySchedule(id)
			})
			console.groupEnd('destroyMultipleSchedules')
			return student
		})
	}

	// area-of-study methods

	get areasByType() {
		return this.studies.groupBy((study) => study.type)
	}

	addArea(areaOfStudy) {
		let study = new Study(areaOfStudy)
		return this.setIn(['studies', study.id], study)
	}

	removeArea(id) {
		return this.set('studies', this.studies.delete(id))
	}

	removeMultipleAreas(ids) {
		Seq(ids).forEach(this.removeArea, this)
	}

	// override methods

	addOverride(override) {
		return this.setIn(['overrides', override.id], override)
	}

	removeOverride(overrideId) {
		return this.set('overrides', this.overrides.delete(overrideId))
	}

	// fabrication methods

	addFabrication(fabrication) {
		return this.setIn(['fabrications', fabrication.id], fabrication)
	}

	removeFabrication(fabricationId) {
		return this.set('fabrications', this.fabrications.delete(fabricationId))
	}

	// getters

	get courses() {
		let allCourses = this.activeSchedules.map((schedule) => schedule.courses).toArray()
		let scheduleCoursePromises = Promise.all(allCourses)
		return scheduleCoursePromises.then((results) => _.flatten(results))
	}

	get creditCount() {
		return this.courses.then(countCredits)
	}

	// helpers

	data() {
		return Promise.props({
			courses: this.courses,
			fabrications: this.fabrications.toList().toJS(),
			overrides: this.overrides.toList().toJS(),
			studies: this.studies.toList().toJS(),
			creditsNeeded: this.creditsNeeded,
			graduation: this.graduation,
			matriculation: this.matriculation,
		})
	}

	encode() {
		return encodeURIComponent(this.toJS())
	}

	toString() {
		return JSON.stringify(this.toJS())
	}

	toJSON() {
		return JSON.stringify(this.toJS())
	}

	save() {
		console.log(`saving student ${this.name} (${this.id})`)
		localStorage.setItem(this.id, this.toJSON())

		if (this.active)
			localStorage.setItem('activeStudentId', this.id)
	}
}

export default Student
<|endoftext|>


<commit_before>var app = angular.module('app', [
    'ui.router',
    'chieffancypants.loadingBar',
    'ivpusic.cookie',
    'btford.socket-io'
]);

app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
    $locationProvider.html5Mode(true);
    $urlRouterProvider.otherwise("/projects");

    $stateProvider
        .state('cmn', {
            abstract: true,
            templateUrl: "/app/templates/cmn.html"
        })
        .state('cmn.panel', {
            views: {
                'worker': {
                    templateUrl: '/app/views/worker.html',
                    controller: 'worker'
                },
                'top-panel': {
                    templateUrl: '/app/views/top-panel.html',
                    controller: 'topPanel'
                },
                '': {
                    template: '<ui-view/>'
                },
                'footer': {
                    templateUrl: '/app/views/footer.html'
                }
            }
        })
        .state('cmn.panel.projects', {
            url: '/projects',
            templateUrl: '/app/views/projects.html',
            controller: 'projects'
        })
        .state('cmn.panel.projectsCreate', {
            url: '/projects/create',
            templateUrl: '/app/views/projectsCreate.html',
            controller: 'projectsCreate'
        })
        .state('cmn.panel.project', {
            url: '/projects/:projectId',
            templateUrl: '/app/views/project.html',
            controller: 'project'
        })
        .state('cmn.panel.project.tickets', {
            url: '^/projects/:projectId/tickets',
            templateUrl: '/app/views/tickets.html',
            controller: 'projectTickets'
        })
        .state('cmn.panel.project.messages', {
            url: '^/projects/:projectId/messages',
            templateUrl: '/app/views/messages.html',
            controller: 'projectMessages'
        })
        .state('cmn.panel.project.themes', {
            url: '^/projects/:projectId/themes',
            templateUrl: '/app/views/themes.html',
            controller: 'projectThemes'
        })
        .state('cmn.panel.project.settings', {
            url: '^/projects/:projectId/settings',
            templateUrl: '/app/views/settings.html',
            controller: 'projectSettings'
        })
        .state('cmn.panel.signin', {
            url: '/signin',
            templateUrl: '/app/views/signin.html',
            controller: 'signin'
        })
        .state('cmn.panel.about', {
            url: '/about',
            templateUrl: '/app/views/about.html'
        })
    });

app.constant('config', {
    apiUrl: '//api.mootkit.lc',
    socketUrl: 'api.mootkit.lc',
    domain: 'mootkit.lc'
});

app.run(['$rootScope', 'cfpLoadingBar', 'auth',
    function ($rootScope, cfpLoadingBar, auth) {
        $rootScope.$on('$stateChangeStart', function() {
            cfpLoadingBar.start();
        });

        $rootScope.$on('$stateChangeSuccess', function() {
            cfpLoadingBar.complete();
        });
        auth.init();
    }]);
<commit_msg>url fixes<commit_after>var app = angular.module('app', [
    'ui.router',
    'chieffancypants.loadingBar',
    'ivpusic.cookie',
    'btford.socket-io'
]);

app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
    $locationProvider.html5Mode(true);
    $urlRouterProvider.otherwise("/projects");

    $stateProvider
        .state('cmn', {
            abstract: true,
            templateUrl: "/app/templates/cmn.html"
        })
        .state('cmn.panel', {
            views: {
                'worker': {
                    templateUrl: '/app/views/worker.html',
                    controller: 'worker'
                },
                'top-panel': {
                    templateUrl: '/app/views/top-panel.html',
                    controller: 'topPanel'
                },
                '': {
                    template: '<ui-view/>'
                },
                'footer': {
                    templateUrl: '/app/views/footer.html'
                }
            }
        })
        .state('cmn.panel.projects', {
            url: '/projects',
            templateUrl: '/app/views/projects.html',
            controller: 'projects'
        })
        .state('cmn.panel.projectsCreate', {
            url: '/projects/create',
            templateUrl: '/app/views/projectsCreate.html',
            controller: 'projectsCreate'
        })
        .state('cmn.panel.project', {
            url: '/projects/:projectId',
            templateUrl: '/app/views/project.html',
            controller: 'project'
        })
        .state('cmn.panel.project.tickets', {
            url: '^/projects/:projectId/tickets',
            templateUrl: '/app/views/tickets.html',
            controller: 'projectTickets'
        })
        .state('cmn.panel.project.messages', {
            url: '^/projects/:projectId/messages',
            templateUrl: '/app/views/messages.html',
            controller: 'projectMessages'
        })
        .state('cmn.panel.project.themes', {
            url: '^/projects/:projectId/themes',
            templateUrl: '/app/views/themes.html',
            controller: 'projectThemes'
        })
        .state('cmn.panel.project.settings', {
            url: '^/projects/:projectId/settings',
            templateUrl: '/app/views/settings.html',
            controller: 'projectSettings'
        })
        .state('cmn.panel.signin', {
            url: '/signin',
            templateUrl: '/app/views/signin.html',
            controller: 'signin'
        })
        .state('cmn.panel.about', {
            url: '/about',
            templateUrl: '/app/views/about.html'
        })
    });

app.constant('config', {
    apiUrl: '//api.mootkit.me',
    socketUrl: 'api.mootkit.me',
    domain: 'mootkit.me'
});

app.run(['$rootScope', 'cfpLoadingBar', 'auth',
    function ($rootScope, cfpLoadingBar, auth) {
        $rootScope.$on('$stateChangeStart', function() {
            cfpLoadingBar.start();
        });

        $rootScope.$on('$stateChangeSuccess', function() {
            cfpLoadingBar.complete();
        });
        auth.init();
    }]);
<|endoftext|>


<commit_before>// @flow
import { combineReducers } from 'redux';
import { routerReducer as routing } from 'react-router-redux';

const rootReducer = combineReducers({
  routing
});

export default rootReducer;
<commit_msg>Imported canvas reducer<commit_after>// @flow
import { combineReducers } from 'redux';
import { routerReducer as routing } from 'react-router-redux';
import { canvas } from 'canvas';

const rootReducer = combineReducers({
	canvas,
	routing
});

export default rootReducer;
<|endoftext|>


<commit_before>const DEFAULT_STATE = {
  searchTerm: ''
};

const rootReducer = (state = DEFAULT_STATE, action) => {
  switch (action.type) {
    default:
      return state;
  }
};

export default rootReducer;
<commit_msg>Adding setSearchTerm reducer<commit_after>import { SET_SEARCH_TERM } from '../actions';

const DEFAULT_STATE = {
  searchTerm: ''
};

const setSearchTerm = (state, action) => Object.assign({}, state, { searchTerm: action.payload });

const rootReducer = (state = DEFAULT_STATE, action) => {
  switch (action.type) {
    case SET_SEARCH_TERM:
      return setSearchTerm(state, action);
    default:
      return state;
  }
};

export default rootReducer;
<|endoftext|>


<commit_before>import R from 'ramda';
import { NODE_DELETE, LINK_ADD, LINK_DELETE } from '../actionTypes';
import {
  getPinsByNodeIdInPatch,
  getLinksByPinIdInPatch,
} from '../selectors/project';
import {
  currentPatchHasThatPins,
  currentPatchHasThatNode,
  getCurrentPatchId,
} from '../utils/reducerUtils';

const nodeIds = (links) =>
  R.map(link => parseInt(link.id, 10))(R.values(links));

export const lastId = (links) => {
  const ids = nodeIds(links);
  // -1 is important because if nodes store doesn't contain nodes then we should return 0 as newId
  return R.reduce(R.max, 0, ids);
};

export const newId = (links) => lastId(links) + 1;

export const copyLink = (link) => R.clone(link);

export const links = (state = {}, action, projectState) => {
  let newLink = null;

  switch (action.type) {
    case LINK_ADD: {
      if (!currentPatchHasThatPins(state, action.payload.pins, projectState)) { return state; }

      newLink = {
        pins: action.payload.pins,
      };
      newLink.id = newId(state);
      return R.set(R.lensProp(newLink.id), newLink, state);
    }
    case NODE_DELETE: {
      if (!currentPatchHasThatNode(state, action.payload.id, projectState)) { return state; }

      const patchId = getCurrentPatchId(state, projectState);
      const pinsToDelete = getPinsByNodeIdInPatch(
        projectState,
        {
          id: action.payload.id,
          patchId,
        }
      );
      const linksToDelete = R.pipe(
        R.values,
        R.reduce((prev, c) => {
          const pinLinks = getLinksByPinIdInPatch(
            projectState,
            {
              pinIds: [c.id],
              patchId,
            }
          );
          return R.concat(prev, R.keys(pinLinks));
        }, [])
      )(pinsToDelete);
      return R.omit(linksToDelete, state);
    }
    case LINK_DELETE:
      return R.omit([action.payload.id.toString()], state);
    default:
      return state;
  }
};
<commit_msg>fix(linksReducer): remove unneded methods and replace one with new selector<commit_after>import R from 'ramda';
import { NODE_DELETE, LINK_ADD, LINK_DELETE } from '../actionTypes';
import {
  getPinsByNodeIdInPatch,
  getLinksByPinIdInPatch,
  getLastLinkId,
} from '../selectors/project';
import {
  currentPatchHasThatPins,
  currentPatchHasThatNode,
  getCurrentPatchId,
} from '../utils/reducerUtils';

export const copyLink = (link) => R.clone(link);

export const links = (state = {}, action, projectState) => {
  let newLink = null;

  switch (action.type) {
    case LINK_ADD: {
      if (!currentPatchHasThatPins(state, action.payload.pins, projectState)) { return state; }

      newLink = {
        pins: action.payload.pins,
      };
      newLink.id = getLastLinkId(projectState) + 1;
      return R.set(R.lensProp(newLink.id), newLink, state);
    }
    case NODE_DELETE: {
      if (!currentPatchHasThatNode(state, action.payload.id, projectState)) { return state; }

      const patchId = getCurrentPatchId(state, projectState);
      const pinsToDelete = getPinsByNodeIdInPatch(
        projectState,
        {
          id: action.payload.id,
          patchId,
        }
      );
      const linksToDelete = R.pipe(
        R.values,
        R.reduce((prev, c) => {
          const pinLinks = getLinksByPinIdInPatch(
            projectState,
            {
              pinIds: [c.id],
              patchId,
            }
          );
          return R.concat(prev, R.keys(pinLinks));
        }, [])
      )(pinsToDelete);
      return R.omit(linksToDelete, state);
    }
    case LINK_DELETE:
      return R.omit([action.payload.id.toString()], state);
    default:
      return state;
  }
};
<|endoftext|>


<commit_before>const initialItems = {
  gettingList     : false,
  list            : [],
  gettingStatuses : false,
  statuses        : []
};

export default function listsReducer (items = initialItems, action) {
  let _items = Object.assign({}, items);
  switch (action.type) {
    case 'SYSTEM_ERROR':
      _items.gettingList = false;
      _items.gettingStatuses = false;
      break;
    case 'REQUEST_GET_LIST':
      _items.gettingList = true;
      break;
    case 'SUCCESS_GET_LIST':
      _items.gettingList = false;
      _items.list = action.payload.data;
      break;
    case 'FAILURE_GET_LIST':
      _items.gettingList = false;
      break;
    case 'REQUEST_GET_LISTS_STATUSES':
      _items.gettingStatuses = true;
      break;
    case 'SUCCESS_GET_LISTS_STATUSES':
      _items.gettingStatuses = false;
      _items.statuses = action.payload.data;
      break;
    case 'FAILURE_GET_LISTS_STATUSES':
      _items.gettingStatuses = false;
      break;
    default:
      break;
  }
  return _items;
};
<commit_msg>[clean] improve code<commit_after>const initialState = {
  gettingList     : false,
  list            : [],
  gettingStatuses : false,
  statuses        : []
};

export default function listsReducer (state = initialState, action) {
  switch (action.type) {
    case 'SYSTEM_ERROR':
      return {
        ...state,
        gettingList     : false,
        gettingStatuses : false
      };

    case 'REQUEST_GET_LIST':
      return {
        ...state,
        gettingList     : true
      };

    case 'SUCCESS_GET_LIST':
      return {
        ...state,
        gettingList : false,
        list : action.payload.data
      };

    case 'FAILURE_GET_LIST':
      return {
        ...state,
        gettingList : false
      };

    case 'REQUEST_GET_LISTS_STATUSES':
      return {
        ...state,
        gettingStatuses : true
      };

    case 'SUCCESS_GET_LISTS_STATUSES':
      return {
        ...state,
        gettingStatuses : false,
        statuses : action.payload.data
      };

    case 'FAILURE_GET_LISTS_STATUSES':
      return {
        ...state,
        gettingStatuses : false
      };

    default:
      break;
  }
  return state;
};
<|endoftext|>


<commit_before>var path = process.cwd();
var Yelp = require('yelp');
var multer  = require('multer');
var upload = multer({ dest: 'uploads/' });
var handlebars  = require('handlebars');
var fs = require('fs');
var session = require('express-session');
var Users = require('../models/users.js');
var Nightclubs = require('../models/nightlife.js');

module.exports = function (app, passport) {

function isLoggedIn (req, res, next) {
        if (req.isAuthenticated()) {
            return next();
        } else {
            res.redirect('/login');
        }
    }

function removeFromClub(checkinID, userID){
           Nightclubs.findOne({'id':checkinID}, function(err,Nightclub){
            if (err) throw err;
            if(Nightclub){
                console.log ("before remove:" +Nightclub.nightclub.users  );
                var user = Nightclub.nightclub.users.indexOf(userID);
                Nightclub.nightclub.users.splice(user, 1);
                console.log ("after remove:" +Nightclub.nightclub.users  );
            } else {
                console.log ("nightclub not found - error?")
            }
        });

}

function addtoClub(checkinID, userID){

}

app.route('/checkin/:checkinID')
  .get(isLoggedIn, function (req, res) {
    //  console.log(req.user);

       Users.findOne({ 'id': req.id }, function (err, User) {
            if (err) throw err;
            if(User){
                console.log("Old location:" + User.nightclub.nightclub);
                if (User.nightclub.nightclub.length >0){
                    removeFromClub(User.nightclub.nightclub, req.ID);
                }
                User.nightclub.nightclub = req.params.checkinID;
                console.log("New location:" + User.nightclub.nightclub);
                User.save();
            } else{
                console.log ("err no user");
            }
        });

       res.sendFile(path + '/public/checkin.html');

  })
}
<commit_msg>add to nightclub data<commit_after>var path = process.cwd();
var Yelp = require('yelp');
var multer  = require('multer');
var upload = multer({ dest: 'uploads/' });
var handlebars  = require('handlebars');
var fs = require('fs');
var session = require('express-session');
var Users = require('../models/users.js');
var Nightclubs = require('../models/nightlife.js');

module.exports = function (app, passport) {

function isLoggedIn (req, res, next) {
        if (req.isAuthenticated()) {
            return next();
        } else {
            res.redirect('/login');
        }
    }

function removeFromClub(checkinID, userID){
           Nightclubs.findOne({'id':checkinID}, function(err,Nightclub){
            if (err) throw err;
            if(Nightclub){
                //if nightclub is found remove user from array and save.
                console.log ("before remove:" +Nightclub.nightclub.users  );
                var user = Nightclub.nightclub.users.indexOf(userID);
                Nightclub.nightclub.users.splice(user, 1);
                console.log ("after remove:" +Nightclub.nightclub.users  );
                Nightclub.save();
            } else {
                console.log ("nightclub not found - error?")
            }
        });

}

function addtoClub(checkinID, userID){
         Nightclubs.findOne({'id':checkinID}, function(err,Nightclub){
            if (err) throw err;
            if(Nightclub){
                //if nightclub is found just add user to users array
                console.log ("before add:" +Nightclub.nightclub.users  );
                Nightclub.nightclub.users.push(userID);
                console.log ("after add:" +Nightclub.nightclub.users  );
                Nightclub.save();
            } else {
               // create new nightclub object
               var  newNightclub = new Nightclub();
               newNightclub.nightclub.id = checkinID;
               newNightclub.nightclub.users.push(userID);
                newNightclub.save(function (err, doc) {
                     if (err) { throw err; }
                });
                console.log (newNightclub);
            }

         });
}

app.route('/checkin/:checkinID')
  .get(isLoggedIn, function (req, res) {
    //  console.log(req.user);

       Users.findOne({ 'id': req.id }, function (err, User) {
            if (err) throw err;
            if(User){
                console.log("Old location:" + User.nightclub.nightclub);
                if (User.nightclub.nightclub.length >0){
                    removeFromClub(User.nightclub.nightclub, req.ID);
                }
                addtoClub(User.nightclub.nightclub, req.ID);
                User.nightclub.nightclub = req.params.checkinID;
                console.log("New location:" + User.nightclub.nightclub);
                User.save();
            } else{
                console.log ("err no user");
            }
        });

       res.sendFile(path + '/public/checkin.html');

  })
}
<|endoftext|>