<commit_before>(function () {
  'use strict';
  angular
    .module('polls')
    .controller('PollsListController', PollsListController);

  PollsListController.$inject = [
    '$rootScope',
    '$state',
    '$scope',
    '$window',
    'Socket',
    'Authentication',
    'Action',
    'toastr',
    'ngDialog',
    'Storages',
    'Constants',
    'UserApi'
  ];

  function PollsListController(
    $rootScope,
    $state,
    $scope,
    $window,
    Socket,
    Authentication,
    Action,
    toast,
    dialog,
    Storages,
    Constants,
    UserApi
  ) {
    var vm = this;
    $scope.user = Authentication.user;
    $scope.isLogged = ($scope.user);

    vm.polls = [];
    vm.hot_polls = [];
    vm.activitys = JSON.parse(Storages.get_session(Constants.storages.activitys, JSON.stringify([])));
    vm.categorys = [];
    vm.bookmarks = [];
    vm.tags = [];
    vm.new_data = [];
    vm.page = 0;
    vm.busy = false;
    vm.stopped = false;
    vm.get_polls = get_polls;
    vm.is_has_new_polls = false;
    init();

    function init() {
      // Lắng nghe sự kiện từ rootScope;
      initRootScope();
      // Lắng nghe sự liện từ socket
      initSocket();
      // Load danh sách category (Bao gồm số poll)
      get_categorys();
      // Load danh sách tags (Bao gồm số poll)
      get_popular_tags();
      // Load các polls có lượng like nhiều nhất
      get_populars();
      // Load danh sách poll đã bookmark
      if ($scope.isLogged) {
        get_bookmarks();
      }
    }

    function initSocket() {
      if (!Socket.socket) {
        Socket.connect();
      }
      Socket.emit('subscribe_public');
      Socket.on('poll_create', () => {
        vm.is_has_new_polls = true;
      });
      $scope.$on('$destroy', function () {
        Socket.emit('unsubscribe_public');
        Socket.removeListener('poll_create');
      });
    }

    function initRootScope() {
      $rootScope.$on('activity', (event, data) => {
        console.log('Has new activity');
        vm.activitys = JSON.parse(Storages.get_session(Constants.storages.activitys, JSON.stringify([])));
        event.stopPropagation();
      });
    }
    function get_polls() {
      if (vm.stopped || vm.busy) return;
      vm.busy = true;
      Action.get_polls(vm.page)
        .then(res => {
          if (!res.data.length || res.data.length === 0) {
            vm.stopped = true;
            vm.busy = false;
            return;
          }
          // Load options và tính vote cho các opt trong polls
          vm.new_data = res.data || [];
          // Xử lý poll trước khi hiển thị màn hình
          var promises = [];
          vm.new_data.forEach(poll => {
            promises.push(process_before_show(poll));
          });
          return Promise.all(promises);
        })
        .then(results => {
          // Gán data vào list hiện tại
          results = results || [];
          vm.polls = _.union(vm.polls, results);
          vm.page += 1;
          vm.busy = false;
          $scope.$apply();
          vm.new_data = [];
        })
        .catch(err => {
          vm.busy = false;
          vm.stopped = true;
          toast.error(err.message, 'Error!');
        });
    }
    function process_before_show(poll) {
      return new Promise((resolve, reject) => {
        poll = Action.process_before_show(poll);
        return resolve(poll);
      });
    }
    function get_populars() {
      Action.get_populars(0)
        .then(res => {
          vm.populars = res.data;
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    }
    function get_categorys() {
      Action.get_categorys()
        .then(res => {
          vm.categorys = res;
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    }
    function get_popular_tags() {
      Action.get_popular_tags()
        .then(res => {
          vm.tags = res.data;
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    }
    function get_bookmarks() {
      UserApi.get_bookmarks($scope.user._id, 0)
        .then(res => {
          vm.bookmarks = res.data || [];
        }, err => {
          toast.error(err.message, 'Error!');
        });
    }
    // Thao tác khác
    $scope.delete_poll = (poll) => {
      if (!poll.isCurrentUserOwner) {
        toast.error('You are not authorized.', 'Error!');
        return;
      }
      $scope.message_title = 'Delete poll!';
      $scope.message_content = 'Are you sure you want to delete this poll?';
      $scope.dialog_type = 3;
      $scope.buton_label = 'delete';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_delete();
      }, reject => {
      });
      function handle_delete() {
        vm.polls = _.without(vm.polls, poll);
        Action.delete_poll(poll);
      }
    };
    $scope.report_poll = (poll) => {
      if (poll.reported) {
        toast.error('You are already reported ' + poll.title, 'Error!');
        return;
      }
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/report.dialog.template.html'
      }).then(reason => {
        handle_confirm(reason);
      }, reject => {
      });
      function handle_confirm(reason) {
        Action.save_report(poll, reason)
          .then(res => {
            poll.reported = (res) ? true : false;
            toast.success('You have successfully reported ' + poll.title, 'Thank you!');
          })
          .catch(err => {
            toast.error(err.message, 'Error!');
          });
      }
    };
    $scope.bookmark_poll = (poll) => {
      if (poll.bookmarked) {
        toast.error('You are already bookmark ' + poll.title, 'Error!');
        return;
      }
      Action.save_bookmark(poll._id)
        .then(res => {
          poll.bookmarked = (res) ? true : false;
          toast.success('Added ' + poll.title + ' to bookmarks.', 'Success!');
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    };
    $scope.follow_poll = (poll) => {
      if (!$scope.isLogged) {
        toast.error('You must login to follow poll.', 'Error!');
        return;
      }
      Action.save_follow(poll.follow)
        .then(res => {
          if (res) {
            poll.follow = res;
            toast.success('You followed ' + poll.title, 'Success!');
          } else {
            poll.follow = { poll: poll._id };
          }
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    };
    $scope.load_new = () => {
      $state.reload();
    };
  }
})();
<commit_msg>Commited from lenh at Tue, Aug 15, 2017  2:01:34 PM<commit_after>(function () {
  'use strict';
  angular
    .module('polls')
    .controller('PollsListController', PollsListController);

  PollsListController.$inject = [
    '$rootScope',
    '$state',
    '$scope',
    '$window',
    'Socket',
    'Authentication',
    'Action',
    'toastr',
    'ngDialog',
    'Storages',
    'Constants',
    'UserApi'
  ];

  function PollsListController(
    $rootScope,
    $state,
    $scope,
    $window,
    Socket,
    Authentication,
    Action,
    toast,
    dialog,
    Storages,
    Constants,
    UserApi
  ) {
    var vm = this;
    $scope.user = Authentication.user;
    $scope.isLogged = ($scope.user);

    vm.polls = [];
    vm.hot_polls = [];
    vm.activitys = JSON.parse(Storages.get_session(Constants.storages.activitys, JSON.stringify([])));
    vm.categorys = [];
    vm.bookmarks = [];
    vm.tags = [];
    vm.new_data = [];
    vm.page = 0;
    vm.busy = false;
    vm.stopped = false;
    vm.get_polls = get_polls;
    vm.is_has_new_polls = false;
    init();

    function init() {
      // Lắng nghe sự liện từ socket
      initSocket();
      // Load danh sách category (Bao gồm số poll)
      get_categorys();
      // Load danh sách tags (Bao gồm số poll)
      get_popular_tags();
      // Load các polls có lượng like nhiều nhất
      get_populars();
      // Load danh sách poll đã bookmark
      if ($scope.isLogged) {
        // Lắng nghe sự kiện từ rootScope;
        initRootScope();
        get_bookmarks();
      }
    }

    function initSocket() {
      if (!Socket.socket) {
        Socket.connect();
      }
      Socket.emit('subscribe_public');
      Socket.on('poll_create', () => {
        vm.is_has_new_polls = true;
      });
      $scope.$on('$destroy', function () {
        Socket.emit('unsubscribe_public');
        Socket.removeListener('poll_create');
      });
    }

    function initRootScope() {
      $rootScope.$on('activity', (event, data) => {
        console.log('Has new activity');
        vm.activitys = JSON.parse(Storages.get_session(Constants.storages.activitys, JSON.stringify([])));
        event.stopPropagation();
      });
    }
    function get_polls() {
      if (vm.stopped || vm.busy) return;
      vm.busy = true;
      Action.get_polls(vm.page)
        .then(res => {
          if (!res.data.length || res.data.length === 0) {
            vm.stopped = true;
            vm.busy = false;
            return;
          }
          // Load options và tính vote cho các opt trong polls
          vm.new_data = res.data || [];
          // Xử lý poll trước khi hiển thị màn hình
          var promises = [];
          vm.new_data.forEach(poll => {
            promises.push(process_before_show(poll));
          });
          return Promise.all(promises);
        })
        .then(results => {
          // Gán data vào list hiện tại
          results = results || [];
          vm.polls = _.union(vm.polls, results);
          vm.page += 1;
          vm.busy = false;
          $scope.$apply();
          vm.new_data = [];
        })
        .catch(err => {
          vm.busy = false;
          vm.stopped = true;
          toast.error(err.message, 'Error!');
        });
    }
    function process_before_show(poll) {
      return new Promise((resolve, reject) => {
        poll = Action.process_before_show(poll);
        return resolve(poll);
      });
    }
    function get_populars() {
      Action.get_populars(0)
        .then(res => {
          vm.populars = res.data;
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    }
    function get_categorys() {
      Action.get_categorys()
        .then(res => {
          vm.categorys = res;
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    }
    function get_popular_tags() {
      Action.get_popular_tags()
        .then(res => {
          vm.tags = res.data;
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    }
    function get_bookmarks() {
      UserApi.get_bookmarks($scope.user._id, 0)
        .then(res => {
          vm.bookmarks = res.data || [];
        }, err => {
          toast.error(err.message, 'Error!');
        });
    }
    // Thao tác khác
    $scope.delete_poll = (poll) => {
      if (!poll.isCurrentUserOwner) {
        toast.error('You are not authorized.', 'Error!');
        return;
      }
      $scope.message_title = 'Delete poll!';
      $scope.message_content = 'Are you sure you want to delete this poll?';
      $scope.dialog_type = 3;
      $scope.buton_label = 'delete';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_delete();
      }, reject => {
      });
      function handle_delete() {
        vm.polls = _.without(vm.polls, poll);
        Action.delete_poll(poll);
      }
    };
    $scope.report_poll = (poll) => {
      if (poll.reported) {
        toast.error('You are already reported ' + poll.title, 'Error!');
        return;
      }
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/report.dialog.template.html'
      }).then(reason => {
        handle_confirm(reason);
      }, reject => {
      });
      function handle_confirm(reason) {
        Action.save_report(poll, reason)
          .then(res => {
            poll.reported = (res) ? true : false;
            toast.success('You have successfully reported ' + poll.title, 'Thank you!');
          })
          .catch(err => {
            toast.error(err.message, 'Error!');
          });
      }
    };
    $scope.bookmark_poll = (poll) => {
      if (poll.bookmarked) {
        toast.error('You are already bookmark ' + poll.title, 'Error!');
        return;
      }
      Action.save_bookmark(poll._id)
        .then(res => {
          poll.bookmarked = (res) ? true : false;
          toast.success('Added ' + poll.title + ' to bookmarks.', 'Success!');
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    };
    $scope.follow_poll = (poll) => {
      if (!$scope.isLogged) {
        toast.error('You must login to follow poll.', 'Error!');
        return;
      }
      Action.save_follow(poll.follow)
        .then(res => {
          if (res) {
            poll.follow = res;
            toast.success('You followed ' + poll.title, 'Success!');
          } else {
            poll.follow = { poll: poll._id };
          }
        })
        .catch(err => {
          toast.error(err.message, 'Error!');
        });
    };
    $scope.load_new = () => {
      $state.reload();
    };
  }
})();
<|endoftext|>


<commit_before>var player = {
    "name": "Ness",
    "face": 3,
    "skin": [217, 183, 31],
    "hair": 0,
    "hairColor": [0, 0, 0],
    "tshirt": 'e',
    "tColor": [255, 0, 0],
    'pColor': [0, 50, 0],
    'hp': 50,
    'mp': 10,
    'maxhp': 50,
    'maxmp': 10,
    'mapX': 5,
    'mapY': 5,
    'xp': 0,
    'nextLevel': 100,
    'money': 0,
     x: 360,
     y: 100
 };

var command = 'Enter X';
var thingToBeEntered = 'ThingToBeEntered';
var enteredText = '';
var text = document.getElementById('textArea');
var playArea = document.getElementById('playArea');
var sumbit = document.getElementById('submitButtonArea');
var textInput = document.getElementById('textInput');

function pickFace() {
  text.innerHTML = 'Pick a face shape:';
  var thingie = '<button onclick="setFaceShape(0)">()</button> '
  thingie += '<button onclick="setFaceShape(1)">( )</button>';
  thingie += '<button onclick="setFaceShape(2)">(  )</button>';
  thingie += '<button onclick="setFaceShape(3)">(   )</button>';
  thingie += '<button onclick="pickSkin()">OK</button>';
  sumbit.innerHTML = thingie;
}

function submitText() {
  switch(thingToBeEntered) {
    case 'name':
      player.name = enteredText;
      document.getElementById('name').innerHTML = player.name;
      pickFace();
      break;
  }
}

function deleteText() {
  if (enteredText.length > 0) {
    enteredText = enteredText.substr(0,enteredText.length-1);
    text.innerHTML = command + enteredText;
    if (thingToBeEntered == 'name'){
      document.getElementById('name').innerHTML = enteredText;
    }
  }
}

function UConScreenKeyboard() {
  var abc = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
  var thingie = '';
  for (var i = 0; i < abc.length; i++) {
    abc[i] = abc[i].toUpperCase();
    thingie += '<button onclick="enterLetter(\''+ abc[i] + '\')">' + abc[i] + '</button>' ;
    /*
    if (abc[i] == 'P') {
        thingie += '
';
    } */
  }
  thingie += '<button onclick="enterLetter(\' \')">_</button>';
  thingie += '<button onclick="LConScreenKeyboard()">A^a</button>';
  thingie += '<button onclick="deleteText()">Del</button>';
  thingie += '<button onclick="submitText()">OK</button>';
  sumbit.innerHTML = thingie;
}

function LConScreenKeyboard() {
  var abc = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
  var thingie = '';
  for (var i = 0; i < abc.length; i++) {
    thingie += '<button onclick="enterLetter(\''+ abc[i] + '\')">' + abc[i] + '</button>' ;
      /*
    if (abc[i] == 'p') {
        thingie += '
';
    } */
  }
  thingie += '<button onclick="enterLetter(\' \')">_</button>';
  thingie += '<button onclick="UConScreenKeyboard()">a^A</button>';
  thingie += '<button onclick="deleteText()">Del</button>';
  thingie += '<button onclick="submitText()">OK</button>';
  sumbit.innerHTML = thingie;
}

function enterLetter(l) {
  enteredText += l;
  text.innerHTML = command + enteredText;
  if (thingToBeEntered == 'name'){
    document.getElementById('name').innerHTML = enteredText;
  }
  if (enteredText.length = 1) {
    LConScreenKeyboard();
  }
}

function enterName() {
  command = 'Enter name: ';
  text.innerHTML = command;
  thingToBeEntered = 'name';
  enteredText = '';
  text.innerHTML = command + enteredText;
  document.getElementById('name').innerHTML = enteredText;
  UConScreenKeyboard();
}

function isOK() {
    text.innerHTML = 'Is this OK?';
    var thingie = '<button onclick="start()">YES</button> ';
    thingie += '<button onclick="enterName()">NO</button> ';
    sumbit.innerHTML = thingie;
}

function pickSkin() {
     text.innerHTML = 'Pick skin tone:';
     var thingie = '<button class="skin0" onclick="setSkinTone(0)">_</button> ';
     thingie += '<button class="skin1" onclick="setSkinTone(1)">_</button> ';
     thingie += '<button class="skin2" onclick="setSkinTone(2)">_</button> ';
     thingie += '<button class="skin3" onclick="setSkinTone(3)">_</button> ';
     thingie += '<button class="skin4" onclick="setSkinTone(4)">_</button> ';
     thingie += '<button onclick="pickHairColor()">OK</button>';
     sumbit.innerHTML = thingie;
}

function pickHairColor() {
     text.innerHTML = 'Pick hair color:';
     var thingie = '<button class="hair0" onclick="setHairColor(0)">_</button> ';
     thingie += '<button class="hair1" onclick="setHairColor(1)">_</button> ';
     thingie += '<button class="hair2" onclick="setHairColor(2)">_</button> ';
     thingie += '<button class="hair3" onclick="setHairColor(3)">_</button> ';
     thingie += '<button class="hair4" onclick="setHairColor(4)">_</button> ';
     thingie += '<button class="hair5" onclick="setHairColor(5)">_</button> ';
     thingie += '<button onclick="pickShirt()">OK</button>';
     sumbit.innerHTML = thingie;
}

function setHairColor(o) {
  switch(o) {
      case 0:
        player.hairColor = [0,0,0];
        break;
      case 1:
        player.hairColor = [59,48,36];
        break;
      case 2:
        player.hairColor = [106,78,66];
        break;
      case 3:
        player.hairColor = [165,107,70];
        break;
      case 4:
        player.hairColor = [181,82,57];
        break;
      case 5:
        player.hairColor = [230,206,168];
        break;
  }
}

function pickShirtColor() {
     text.innerHTML = 'Pick shirt color:';
     var thingie = '<button class="shirt0" onclick="setShirtColor(0)">_</button> ';
     thingie += '<button class="shirt1" onclick="setShirtColor(1)">_</button> ';
     thingie += '<button class="shirt2" onclick="setShirtColor(2)">_</button> ';
     thingie += '<button class="pants3" onclick="setShirtColor(3)">_</button> ';
     thingie += '<button onclick="pickPantsColor()">OK</button> ';
     sumbit.innerHTML = thingie;
}

function setShirtColor(o) {
  switch(o) {
  case 0:
    player.tColor = [255,0,0];
    break;
  case 1:
    player.tColor = [0,100,0];
    break;
  case 2:
    player.tColor = [0,0,255];
    break;
  case 3:
    player.tColor = [0,0,0];
    break;
  }
}

function setPantsColor(o) {
  switch(o) {
  case 0:
    player.pColor = [50,0,0];
    break;
  case 1:
    player.pColor = [0,50,0];
    break;
  case 2:
    player.pColor = [0,0,50];
    break;
  case 2:
    player.pColor = [0,0,0];
    break;
  }
}

function pickPantsColor() {
    text.innerHTML = 'Pick pants color:';
    var thingie = '<button class="pants0" onclick="setPantsColor(0)">_</button> ';
    thingie += '<button class="pants1" onclick="setPantsColor(1)">_</button> ';
    thingie += '<button class="pants2" onclick="setPantsColor(2)">_</button> ';
    thingie += '<button class="pants3" onclick="setPantsColor(3)">_</button> ';
    thingie += '<button class="pants3" onclick="isOK()">OK</button> ';
    sumbit.innerHTML = thingie;
}

function pickShirt() {
     text.innerHTML = 'Pick tshirt logo:';
     var thingie = '<button onclick="setTshirt(2.7)">e</button> ';
     thingie += '<button onclick="setTshirt(3.14)">π</button> ';
     thingie += '<button onclick="setTshirt(6.2)">τ</button> ';
     thingie += '<button onclick="setTshirt(0)">ϕ</button> ';
     thingie += '<button onclick="setTshirt(1)">μ</button> ';
     thingie += '<button onclick="setTshirt(2)">λ</button> ';
     thingie += '<button onclick="pickShirtColor()">OK</button>';
     sumbit.innerHTML = thingie;
}

function setTshirt(o) {
  switch(o) {
   case 3.14:
     player.tshirt = 'π';
     break;
   case 2.7:
     player.tshirt = 'e';
     break;
   case 6.2:
     player.tshirt = 'τ';
     break;
   case 0:
     player.tshirt = 'ϕ';
     break;
   case 1:
     player.tshirt = 'μ';
     break;
   case 2:
     player.tshirt = 'λ';
     break;
  }
}

function setFaceShape(o) {
  player.face = o;
  reload();
}

function setSkinTone(o) {
  switch(o) {
  case 0:
    player.skin = [141,85,36];
    break;
  case 1:
    player.skin = [198,134,66];
    break;
  case 2:
    player.skin = [224,172,105];
    break;
  case 3:
    player.skin = [241,194,125];
    break;
  case 4:
    player.skin = [255,219,172];
    break;
  }

}

function updateStats() {
    document.getElementById('hp').innerHTML = 'HP: ' + player.hp + '/' + player.maxhp;
    document.getElementById('mp').innerHTML = 'MP: ' + player.mp + '/' + player.maxmp;
    document.getElementById('xp').innerHTML = 'XP: ' + player.xp + '/' + player.nextLevel;
    document.getElementById('money').innerHTML = '$' + player.money;
}

enterName();
updateStats();
<commit_msg>Update charCreation.js<commit_after>var player = {
    "name": "Ness",
    "face": 3,
    "skin": [217, 183, 31],
    "hair": 0,
    "hairColor": [0, 0, 0],
    "tshirt": 'e',
    "tColor": [255, 0, 0],
    'pColor': [0, 50, 0],
    'hp': 50,
    'mp': 10,
    'maxhp': 50,
    'maxmp': 10,
    'mapX': 5,
    'mapY': 5,
    'xp': 0,
    'nextLevel': 100,
    'money': 0,
     x: 360,
     y: 100
 };

var command = 'Enter X';
var thingToBeEntered = 'ThingToBeEntered';
var enteredText = '';
var text = document.getElementById('textArea');
var playArea = document.getElementById('playArea');
var sumbit = document.getElementById('submitButtonArea');
var textInput = document.getElementById('textInput');

function pickFace() {
  text.innerHTML = 'Pick a face shape:';
  var thingie = '<button onclick="setFaceShape(0)">()</button> '
  thingie += '<button onclick="setFaceShape(1)">( )</button>';
  thingie += '<button onclick="setFaceShape(2)">(  )</button>';
  thingie += '<button onclick="setFaceShape(3)">(   )</button>';
  thingie += '<button onclick="pickSkin()">OK</button>';
  sumbit.innerHTML = thingie;
}

function submitText() {
  switch(thingToBeEntered) {
    case 'name':
      player.name = enteredText;
      document.getElementById('name').innerHTML = player.name;
      pickFace();
      break;
  }
}

function deleteText() {
  if (enteredText.length > 0) {
    enteredText = enteredText.substr(0,enteredText.length-1);
    text.innerHTML = command + enteredText;
    if (thingToBeEntered == 'name'){
      document.getElementById('name').innerHTML = enteredText;
    }
  }
}

function UConScreenKeyboard() {
  var abc = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
  var thingie = '';
  for (var i = 0; i < abc.length; i++) {
    abc[i] = abc[i].toUpperCase();
    thingie += '<button onclick="enterLetter(\''+ abc[i] + '\')">' + abc[i] + '</button>' ;
    /*
    if (abc[i] == 'P') {
        thingie += '
';
    } */
  }
  thingie += '<button onclick="enterLetter(\' \')">_</button>';
  thingie += '<button onclick="LConScreenKeyboard()">A^a</button>';
  thingie += '<button onclick="deleteText()">Del</button>';
  thingie += '<button onclick="submitText()">OK</button>';
  sumbit.innerHTML = thingie;
}

function LConScreenKeyboard() {
  var abc = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
  var thingie = '';
  for (var i = 0; i < abc.length; i++) {
    thingie += '<button onclick="enterLetter(\''+ abc[i] + '\')">' + abc[i] + '</button>' ;
      /*
    if (abc[i] == 'p') {
        thingie += '
';
    } */
  }
  thingie += '<button onclick="enterLetter(\' \')">_</button>';
  thingie += '<button onclick="UConScreenKeyboard()">a^A</button>';
  thingie += '<button onclick="deleteText()">Del</button>';
  thingie += '<button onclick="submitText()">OK</button>';
  sumbit.innerHTML = thingie;
}

function enterLetter(l) {
  enteredText += l;
  text.innerHTML = command + enteredText;
  if (thingToBeEntered == 'name'){
    document.getElementById('name').innerHTML = enteredText;
  }
  if (enteredText.length = 1) {
    LConScreenKeyboard();
  }
}

function enterName() {
  command = 'Enter name: ';
  text.innerHTML = command;
  thingToBeEntered = 'name';
  enteredText = '';
  text.innerHTML = command + enteredText;
  document.getElementById('name').innerHTML = enteredText;
  UConScreenKeyboard();
}

function isOK() {
    text.innerHTML = 'Is this OK?';
    var thingie = '<button onclick="start()">YES</button> ';
    thingie += '<button onclick="enterName()">NO</button> ';
    sumbit.innerHTML = thingie;
}

function pickSkin() {
     text.innerHTML = 'Pick skin tone:';
     var thingie = '<button class="skin0" onclick="setSkinTone(0)">_</button> ';
     thingie += '<button class="skin1" onclick="setSkinTone(1)">_</button> ';
     thingie += '<button class="skin2" onclick="setSkinTone(2)">_</button> ';
     thingie += '<button class="skin3" onclick="setSkinTone(3)">_</button> ';
     thingie += '<button class="skin4" onclick="setSkinTone(4)">_</button> ';
     thingie += '<button onclick="pickHairColor()">OK</button>';
     sumbit.innerHTML = thingie;
}

function pickHairColor() {
     text.innerHTML = 'Pick hair color:';
     var thingie = '<button class="hair0" onclick="setHairColor(0)">_</button> ';
     thingie += '<button class="hair1" onclick="setHairColor(1)">_</button> ';
     thingie += '<button class="hair2" onclick="setHairColor(2)">_</button> ';
     thingie += '<button class="hair3" onclick="setHairColor(3)">_</button> ';
     thingie += '<button class="hair4" onclick="setHairColor(4)">_</button> ';
     thingie += '<button class="hair5" onclick="setHairColor(5)">_</button> ';
     thingie += '<button onclick="pickShirt()">OK</button>';
     sumbit.innerHTML = thingie;
}

function setHairColor(o) {
  switch(o) {
      case 0:
        player.hairColor = [0,0,0];
        break;
      case 1:
        player.hairColor = [59,48,36];
        break;
      case 2:
        player.hairColor = [106,78,66];
        break;
      case 3:
        player.hairColor = [165,107,70];
        break;
      case 4:
        player.hairColor = [181,82,57];
        break;
      case 5:
        player.hairColor = [230,206,168];
        break;
  }
  reload();
}

function pickShirtColor() {
     text.innerHTML = 'Pick shirt color:';
     var thingie = '<button class="shirt0" onclick="setShirtColor(0)">_</button> ';
     thingie += '<button class="shirt1" onclick="setShirtColor(1)">_</button> ';
     thingie += '<button class="shirt2" onclick="setShirtColor(2)">_</button> ';
     thingie += '<button class="pants3" onclick="setShirtColor(3)">_</button> ';
     thingie += '<button onclick="pickPantsColor()">OK</button> ';
     sumbit.innerHTML = thingie;
}

function setShirtColor(o) {
  switch(o) {
  case 0:
    player.tColor = [255,0,0];
    break;
  case 1:
    player.tColor = [0,100,0];
    break;
  case 2:
    player.tColor = [0,0,255];
    break;
  case 3:
    player.tColor = [0,0,0];
    break;
  }
  reload();
}

function setPantsColor(o) {
  switch(o) {
  case 0:
    player.pColor = [50,0,0];
    break;
  case 1:
    player.pColor = [0,50,0];
    break;
  case 2:
    player.pColor = [0,0,50];
    break;
  case 2:
    player.pColor = [0,0,0];
    break;
  }
  reload();
}

function pickPantsColor() {
    text.innerHTML = 'Pick pants color:';
    var thingie = '<button class="pants0" onclick="setPantsColor(0)">_</button> ';
    thingie += '<button class="pants1" onclick="setPantsColor(1)">_</button> ';
    thingie += '<button class="pants2" onclick="setPantsColor(2)">_</button> ';
    thingie += '<button class="pants3" onclick="setPantsColor(3)">_</button> ';
    thingie += '<button class="pants3" onclick="isOK()">OK</button> ';
    sumbit.innerHTML = thingie;
}

function pickShirt() {
     text.innerHTML = 'Pick tshirt logo:';
     var thingie = '<button onclick="setTshirt(2.7)">e</button> ';
     thingie += '<button onclick="setTshirt(3.14)">π</button> ';
     thingie += '<button onclick="setTshirt(6.2)">τ</button> ';
     thingie += '<button onclick="setTshirt(0)">ϕ</button> ';
     thingie += '<button onclick="setTshirt(1)">μ</button> ';
     thingie += '<button onclick="setTshirt(2)">λ</button> ';
     thingie += '<button onclick="pickShirtColor()">OK</button>';
     sumbit.innerHTML = thingie;
}

function setTshirt(o) {
  switch(o) {
   case 3.14:
     player.tshirt = 'π';
     break;
   case 2.7:
     player.tshirt = 'e';
     break;
   case 6.2:
     player.tshirt = 'τ';
     break;
   case 0:
     player.tshirt = 'ϕ';
     break;
   case 1:
     player.tshirt = 'μ';
     break;
   case 2:
     player.tshirt = 'λ';
     break;
  }
  reload();
}

function setFaceShape(o) {
  player.face = o;
  reload();
}

function setSkinTone(o) {
  switch(o) {
  case 0:
    player.skin = [141,85,36];
    break;
  case 1:
    player.skin = [198,134,66];
    break;
  case 2:
    player.skin = [224,172,105];
    break;
  case 3:
    player.skin = [241,194,125];
    break;
  case 4:
    player.skin = [255,219,172];
    break;
  }
  reload();
}

function updateStats() {
    document.getElementById('hp').innerHTML = 'HP: ' + player.hp + '/' + player.maxhp;
    document.getElementById('mp').innerHTML = 'MP: ' + player.mp + '/' + player.maxmp;
    document.getElementById('xp').innerHTML = 'XP: ' + player.xp + '/' + player.nextLevel;
    document.getElementById('money').innerHTML = '$' + player.money;
}

enterName();
updateStats();
<|endoftext|>


<commit_before>var fs = require('fs-extra');
var Blog = require('blog');
var helper = require('helper');
var join = require('path').join;
var blog_dir = join(helper.rootDir, 'blogs');
var load_db = require('../db/load');
var config = require('config');
var access = require('../access');
var DropboxDatabasePrivate = require('../../app/clients/dropbox/database');
var remote = require('../remote');

var DUMP_WITH_TEST_ACCOUNT = 'with_user_empty_blog';
var BLOG_ID = "1";
var DROPBOX_FOLDER_PATH = "/Users/David/Dropbox/Apps/Blot test";

if (require.main === module) {

  var identifier = process.argv[2];

  if (!identifier) throw new Error('Please pass the username of the blog whose folder you want to download');

  main(identifier, function(err){

    if (err) throw err;

    process.exit();
  });
}

// what do  I want from this?
// to be able to say:
// fetch/folder jack and then recieve a log in link:

// 1. load latest remote database containing the username jack
// 2. fetch the contents of jack's folder from remote and install them in his blog directory
// 3. replace his Dropbox sync info with my Dropbox test account
// 4. Copy files from his directory to my Dropbox test account
// 5. generate log in link

function replace_dropbox_account (blog_id, test_account, callback) {

  DropboxDatabasePrivate.set(blog_id, test_account, function(err){

    if (err) return callback(err);

    try {
      fs.emptyDirSync(DROPBOX_FOLDER_PATH);
      fs.copySync(join(blog_dir, blog_id), DROPBOX_FOLDER_PATH);
    } catch (e) {
      return callback(e);
    }

    callback();
  });
}

function dropbox_test_account (callback) {

  load_db(DUMP_WITH_TEST_ACCOUNT, function(err){

    if (err) return callback(err);

    DropboxDatabasePrivate.get(BLOG_ID, callback);
  });
}

function fetch_remote_blog_directory (blog_id, callback) {

  var local_dir = join(blog_dir, blog_id);
  var remote_dir = join(remote.root, 'blogs', blog_id);

  fs.emptyDirSync(local_dir);
  remote.fetchdir(remote_dir, local_dir, callback);
}

function get_blog_id (handle, callback) {

  // Load latest database
  load_db(null, function(err){

    if (err) return callback(err);

    Blog.get({handle: handle}, function(err, blog){

      if (err || !blog) return callback(new Error('No blog with username ' + handle));

      callback(null, blog.id);
    });
  });
}

function main (handle, callback) {

  console.log('Fetching test account...');

  // This must happen before we get the blog ID
  dropbox_test_account(function(err, test_account){

    if (err) return callback(err);

    console.log('Getting blog id for ' + handle + '...');

    // Now we have the production dump loaded
    get_blog_id(handle, function(err, blog_id){

      if (err) return callback(err);

      console.log('Fetching remote directory ' + handle + '...');

      fetch_remote_blog_directory(blog_id, function(err){

        if (err) return callback(err);

        console.log('Replacing dropbox acccount info...');

        replace_dropbox_account(blog_id, test_account, function(err){

          if (err) return callback(err);

          fs.emptyDir(config.cache_directory, function(err){

            if (err) return callback(err);

            access(handle, callback);
          });
        });
      });
    });
  });
}<commit_msg>Updated folder fetching script<commit_after>var fs = require('fs-extra');
var Blog = require('blog');
var helper = require('helper');
var join = require('path').join;
var blog_dir = join(helper.rootDir, 'blogs');
var load_db = require('../db/load');
var config = require('config');
var access = require('../access');
var DropboxDatabasePrivate = require('../../app/clients/dropbox/database');
var remote = require('../remote');

var DUMP_WITH_TEST_ACCOUNT = 'with_user_empty_blog';
var BLOG_ID = "1";
var DROPBOX_FOLDER_PATH = "/Users/David/Dropbox/Apps/Blot test";

if (require.main === module) {

  var identifier = process.argv[2];

  if (!identifier) throw new Error('Please pass the username of the blog whose folder you want to download');

  main(identifier, function(err){

    if (err) throw err;

    process.exit();
  });
}

// what do  I want from this?
// to be able to say:
// fetch/folder jack and then recieve a log in link:

// 1. load latest remote database containing the username jack
// 2. fetch the contents of jack's folder from remote and install them in his blog directory
// 3. replace his Dropbox sync info with my Dropbox test account
// 4. Copy files from his directory to my Dropbox test account
// 5. generate log in link

function replace_dropbox_account (blog_id, test_account, callback) {

  DropboxDatabasePrivate.set(blog_id, test_account, function(err){

    if (err) return callback(err);

    try {
      fs.emptyDirSync(DROPBOX_FOLDER_PATH);
      fs.copySync(join(blog_dir, blog_id), DROPBOX_FOLDER_PATH);
    } catch (e) {
      return callback(e);
    }

    callback();
  });
}

function dropbox_test_account (callback) {

  load_db(DUMP_WITH_TEST_ACCOUNT, function(err){

    if (err) return callback(err);

    DropboxDatabasePrivate.get(BLOG_ID, callback);
  });
}

function fetch_remote_blog_directory (blog_id, callback) {

  var local_dir = join(blog_dir, blog_id);
  var remote_dir = join(remote.root, 'blogs', blog_id);

  console.log('Blog files:', local_dir);

  fs.emptyDirSync(local_dir);
  remote.fetchdir(remote_dir, local_dir, callback);
}

function get_blog_id (handle, callback) {

  // Load latest database
  load_db(null, function(err){

    if (err) return callback(err);

    Blog.get({handle: handle}, function(err, blog){

      if (err || !blog) return callback(new Error('No blog with username ' + handle));

      callback(null, blog.id);
    });
  });
}

function main (handle, callback) {

  console.log('Fetching test account...');

  // This must happen before we get the blog ID
  dropbox_test_account(function(err, test_account){

    if (err) return callback(err);

    console.log('Getting blog id for ' + handle + '...');

    // Now we have the production dump loaded
    get_blog_id(handle, function(err, blog_id){

      if (err) return callback(err);

      console.log('Fetching remote directory ' + handle + '...');

      fetch_remote_blog_directory(blog_id, function(err){

        if (err) return callback(err);

        console.log('Replacing dropbox acccount info...');

        replace_dropbox_account(blog_id, test_account, function(err){

          if (err) return callback(err);

          fs.emptyDir(config.cache_directory, function(err){

            if (err) return callback(err);

            access(handle, callback);
          });
        });
      });
    });
  });
}<|endoftext|>


<commit_before>var encryption = require('./encryption.js');

var client_id = process.env.GITHUB_APP_CLIENT_ID;
var client_secret = process.env.GITHUB_APP_CLIENT_SECRET;
var hostUrl = 'http://github.com/login/oauth/authorize';
var authorization_base_url = 'https://github.com/login/oauth/authorize'
var token_url = 'https://github.com/login/oauth/access_token'
var bot_host = process.env.HUBOT_HOST_URL
var GitHubApi = require('github')
var cache = require('./cache.js').getCache()

module.exports = (robot) => {

    robot.router.get('/auth/github/callback', function (req, res) {
        var userid = JSON.parse(req.query.state).userid;
        var username = JSON.parse(req.query.state).username;

        var code = req.query.code;

        OAuth2.getOAuthAccessToken(code, {}, function (err, access_token) {
            if (err) {
                console.log(err);
            }

            // ****
            // TODO:
            // BETTER Handling of promises!!
            // ****

            var db = require('./mlab-login.js').db();

            github.authenticate({
                "type": "token",
                "token": access_token
            })
            github.users.get({}, function (err, res) {
                var github_username = res.data.login
                db.bind('users').findAndModifyAsync(
                    { _id: userid },
                    [["_id", 1]],
                    { $set: { github_username: github_username } },
                    { upsert: true })
                    .then(res => { })
                    .catch(err => {
                        robot.logger.error(err)
                        if (c.errorsChannel) {
                            robot.messageRoom(c.errorsChannel, c.errorMessage
                                + `Script: ${path.basename(__filename)}`)
                        }
                    })
                var values = {
                    github_username: github_username,
                    github_token: access_token
                }
                cache.set(userid, values)
            })
            encryption.encrypt(access_token).then(encryptedToken => {

                //TODO -> convert to promise
                db.bind('users').findAndModifyAsync(
                    { _id: userid },
                    [["_id", 1]],
                    { $set: { github_token: encryptedToken } },
                    { upsert: true })
                    .then(res => {
                        robot.logger.info(`${username}'s GitHub Token Added to DB!`)
                        robot.emit('refreshBrain') //refresh brain to update tokens
                    })
                    .catch(err => {
                        robot.logger.error(err)
                        if (c.errorsChannel) {
                            robot.messageRoom(c.errorsChannel, c.errorMessage
                                + `Script: ${path.basename(__filename)}`)
                        }
                    })
                    .done(() => {
                        db.close()
                    })
            });
        });
        res.redirect('');
    });

}<commit_msg>gh token.js<commit_after>var encryption = require('./encryption.js');

var client_id = process.env.GITHUB_APP_CLIENT_ID;
var client_secret = process.env.GITHUB_APP_CLIENT_SECRET;
var hostUrl = 'http://github.com/login/oauth/authorize';
var authorization_base_url = 'https://github.com/login/oauth/authorize'
var token_url = 'https://github.com/login/oauth/access_token'
var bot_host = process.env.HUBOT_HOST_URL
var GitHubApi = require('github')
var cache = require('./cache.js').getCache()
var oauth = require("oauth").OAuth2;
var OAuth2 = new oauth(
    client_id,
    client_secret,
    "https://github.com/",
    "login/oauth/authorize",
    "login/oauth/access_token");

module.exports = (robot) => {

    robot.router.get('/auth/github/callback', function (req, res) {
        var userid = JSON.parse(req.query.state).userid;
        var username = JSON.parse(req.query.state).username;

        var code = req.query.code;

        OAuth2.getOAuthAccessToken(code, {}, function (err, access_token) {
            if (err) {
                console.log(err);
            }

            // ****
            // TODO:
            // BETTER Handling of promises!!
            // ****

            var db = require('./mlab-login.js').db();

            github.authenticate({
                "type": "token",
                "token": access_token
            })
            github.users.get({}, function (err, res) {
                var github_username = res.data.login
                db.bind('users').findAndModifyAsync(
                    { _id: userid },
                    [["_id", 1]],
                    { $set: { github_username: github_username } },
                    { upsert: true })
                    .then(res => { })
                    .catch(err => {
                        robot.logger.error(err)
                        if (c.errorsChannel) {
                            robot.messageRoom(c.errorsChannel, c.errorMessage
                                + `Script: ${path.basename(__filename)}`)
                        }
                    })
                var values = {
                    github_username: github_username,
                    github_token: access_token
                }
                cache.set(userid, values)
            })
            encryption.encrypt(access_token).then(encryptedToken => {

                //TODO -> convert to promise
                db.bind('users').findAndModifyAsync(
                    { _id: userid },
                    [["_id", 1]],
                    { $set: { github_token: encryptedToken } },
                    { upsert: true })
                    .then(res => {
                        robot.logger.info(`${username}'s GitHub Token Added to DB!`)
                        robot.emit('refreshBrain') //refresh brain to update tokens
                    })
                    .catch(err => {
                        robot.logger.error(err)
                        if (c.errorsChannel) {
                            robot.messageRoom(c.errorsChannel, c.errorMessage
                                + `Script: ${path.basename(__filename)}`)
                        }
                    })
                    .done(() => {
                        db.close()
                    })
            });
        });
        res.redirect('');
    });

}<|endoftext|>


<commit_before>Router.map(function () {
	this.route('frameSchedule', {
		path: '/frame/schedule',
		layoutTemplate: 'frameLayout',
	});
});

Template.frameSchedule.onCreated(function() {
	var filter = Filtering(EventPredicates);

	var instance = this;
	instance.interval = new ReactiveVar(60);
	instance.scheduleStart = new ReactiveVar(moment());
	instance.separators = new ReactiveVar([]);

	this.autorun(function() {
		var query = Router.current().params.query;

		var scheduleStart;
		if (query.start) scheduleStart = moment(query.start);
		if (!scheduleStart || !scheduleStart.isValid()) scheduleStart = moment(minuteTime.get()).startOf('week');
		instance.scheduleStart.set(scheduleStart);

		var rawSeps = (query.sep || "").split(',');
		var seps = [];
		_.each(rawSeps, function(rawSep) {
			if (rawSep.length == 0) {
				return;
			}

			if (rawSep.length < 3) {
				rawSep = rawSep + "00";
			}

			var hm = parseInt(rawSep, 10);
			if (!isNaN(hm)) {
				var h = Math.floor(hm/100);
				var m = hm % 100;
				seps.push(h*60+m);
			}
		});
		var separators = _.uniq(seps);
		instance.separators.set(separators);

		var readInterval = parseInt(query.interval, 10);
		if (!isNaN(readInterval) && readInterval > 0) {
			instance.interval.set(readInterval);
		} else {
			if (separators.length > 0) {
				instance.interval.set(24*60);
			} else {
				instance.interval.set(60);
			}
		}

		filter.clear().read(query);
		filter.add('after', scheduleStart);
		filter.add('end', moment(scheduleStart).add(1, 'week'));
		filter.done();
	});

	this.autorun(function() {
		subs.subscribe('eventsFind', filter.toQuery(), 100);
	});

	instance.days = new ReactiveVar([]);
	instance.intervals = new ReactiveVar([]);
	instance.slots = new ReactiveVar({});

	this.autorun(function() {
		var scheduleStart = moment(filter.get('after'));
		var end = moment(filter.get('end'));
		var dayCount = end.diff(scheduleStart, 'days');
		var interval = instance.interval.get();

		// Because we need to find the closest separator later on
		// we create a reversed copy which is easier to search
		var separators = instance.separators.get().slice().reverse();

		// List of intervals where events or separators are placed
		var intervals = _.reduce(separators, function(intervals, separator) {
			intervals[separator] = separator;
			return intervals;
		}, {});

		// List of days where events where found
		var days = {};

		// Map of slots where events were found. each slot holds a list of events.
		var slots = {};

		// Place found events into the slots
		eventsFind(filter.toQuery(), 100).forEach(function(event) {
			var eventStart = moment(event.start);
			var dayStart = moment(eventStart).startOf('day');

			var day = dayStart.diff(scheduleStart, 'days');
			days[day] = day;

			var minuteDiff = eventStart.diff(dayStart, 'minutes');
			var intervalStart = Math.floor(minuteDiff / interval) * interval;
			var closestSeparator = _.find(separators, function(sep) {
				return sep < minuteDiff;
			});

			var mins = Math.max(intervalStart, closestSeparator || 0);
			intervals[mins] = mins;

			if (!slots[mins]) slots[mins] = [];
			if (!slots[mins][day]) slots[mins][day] = [];
			slots[mins][day].push(event);
		});

		var numCmp = function(a, b) { return a - b; };
		instance.days.set(_.values(days).sort(numCmp));
		instance.intervals.set(_.values(intervals).sort(numCmp));
		instance.slots.set(slots);
	});
});

Template.frameSchedule.helpers({
	days: function() {
		var instance = Template.instance();
		var scheduleStart = instance.scheduleStart.get();
		return _.map(Template.instance().days.get(), function(day) {
			return moment(scheduleStart).add(day, 'days').format('dddd');
		});
	},

	intervals: function() {
		var slots = Template.instance().slots.get();

		return _.map(Template.instance().intervals.get(), function(mins) {
			return {
				interval: moment().hour(0).minute(mins).format('LT'),
				slots: _.map(Template.instance().days.get(), function(day) {
					return slots[mins] && slots[mins][day];
				})
			}
		});
	},
});<commit_msg>add ranked color class according to event title<commit_after>Router.map(function () {
	this.route('frameSchedule', {
		path: '/frame/schedule',
		layoutTemplate: 'frameLayout',
	});
});

Template.frameSchedule.onCreated(function() {
	var filter = Filtering(EventPredicates);

	var instance = this;
	instance.interval = new ReactiveVar(60);
	instance.scheduleStart = new ReactiveVar(moment());
	instance.separators = new ReactiveVar([]);

	this.autorun(function() {
		var query = Router.current().params.query;

		var scheduleStart;
		if (query.start) scheduleStart = moment(query.start);
		if (!scheduleStart || !scheduleStart.isValid()) scheduleStart = moment(minuteTime.get()).startOf('week');
		instance.scheduleStart.set(scheduleStart);

		var rawSeps = (query.sep || "").split(',');
		var seps = [];
		_.each(rawSeps, function(rawSep) {
			if (rawSep.length == 0) {
				return;
			}

			if (rawSep.length < 3) {
				rawSep = rawSep + "00";
			}

			var hm = parseInt(rawSep, 10);
			if (!isNaN(hm)) {
				var h = Math.floor(hm/100);
				var m = hm % 100;
				seps.push(h*60+m);
			}
		});
		var separators = _.uniq(seps);
		instance.separators.set(separators);

		var readInterval = parseInt(query.interval, 10);
		if (!isNaN(readInterval) && readInterval > 0) {
			instance.interval.set(readInterval);
		} else {
			if (separators.length > 0) {
				instance.interval.set(24*60);
			} else {
				instance.interval.set(60);
			}
		}

		filter.clear().read(query);
		filter.add('after', scheduleStart);
		filter.add('end', moment(scheduleStart).add(1, 'week'));
		filter.done();
	});

	this.autorun(function() {
		subs.subscribe('eventsFind', filter.toQuery(), 100);
	});

	instance.days = new ReactiveVar([]);
	instance.intervals = new ReactiveVar([]);
	instance.slots = new ReactiveVar({});
	instance.kindMap = function() { return 0; };

	this.autorun(function() {
		var scheduleStart = moment(filter.get('after'));
		var end = moment(filter.get('end'));
		var dayCount = end.diff(scheduleStart, 'days');
		var interval = instance.interval.get();

		// Because we need to find the closest separator later on
		// we create a reversed copy which is easier to search
		var separators = instance.separators.get().slice().reverse();

		// List of intervals where events or separators are placed
		var intervals = _.reduce(separators, function(intervals, separator) {
			intervals[separator] = separator;
			return intervals;
		}, {});

		// List of days where events where found
		var days = {};

		// Map of slots where events were found. each slot holds a list of events.
		var slots = {};

		// Count occurences of first few chars in event titles
		var kinds = {};

		// Place found events into the slots
		eventsFind(filter.toQuery(), 100).forEach(function(event) {
			var eventStart = moment(event.start);
			var dayStart = moment(eventStart).startOf('day');

			var day = dayStart.diff(scheduleStart, 'days');
			days[day] = day;

			var minuteDiff = eventStart.diff(dayStart, 'minutes');
			var intervalStart = Math.floor(minuteDiff / interval) * interval;
			var closestSeparator = _.find(separators, function(sep) {
				return sep < minuteDiff;
			});

			var mins = Math.max(intervalStart, closestSeparator || 0);
			intervals[mins] = mins;

			if (!slots[mins]) slots[mins] = [];
			if (!slots[mins][day]) slots[mins][day] = [];
			slots[mins][day].push(event);

			var kindId = event.title.substr(0, 5);
			if (!kinds[kindId]) kinds[kindId] = 1;
			kinds[kindId] += 1;
		});

		var numCmp = function(a, b) { return a - b; };
		instance.days.set(_.values(days).sort(numCmp));
		instance.intervals.set(_.values(intervals).sort(numCmp));
		instance.slots.set(slots);

		// Build list of most used titles (first few chars)
		var mostUsedKinds = _.sortBy(_.pairs(kinds), function(kv) { return -kv[1]; });
		var kindRank = _.object(_.map(mostUsedKinds.slice(0, 15), function(kv, rank) {
			return [kv[0], rank+1];
		}));
		instance.kindMap = function(title) {
			var kindId = title.substr(0, 5);
			if (kindRank[kindId]) return kindRank[kindId];
			return 0;
		};
	});
});

Template.frameSchedule.helpers({
	days: function() {
		var instance = Template.instance();
		var scheduleStart = instance.scheduleStart.get();
		return _.map(Template.instance().days.get(), function(day) {
			return moment(scheduleStart).add(day, 'days').format('dddd');
		});
	},

	intervals: function() {
		var slots = Template.instance().slots.get();

		return _.map(Template.instance().intervals.get(), function(mins) {
			return {
				interval: moment().hour(0).minute(mins).format('LT'),
				slots: _.map(Template.instance().days.get(), function(day) {
					return slots[mins] && slots[mins][day];
				})
			}
		});
	},

	colorClass: function() {
		return "color-"+Template.instance().kindMap(this.title);
	}
});<|endoftext|>


<commit_before>/* eslint-disable no-unused-vars, no-use-before-define */
import { ipcRenderer as ipc, webFrame, remote, shell } from "electron";

import * as path from "path";

import * as fs from "fs";

import { throttle } from "lodash";

import { load, newNotebook } from "@nteract/core/actions";

import { loadConfig } from "@nteract/core/actions";

import {
  toggleCellInputVisibility,
  clearOutputs,
  copyCell,
  createCellAfter,
  cutCell,
  executeCell,
  interruptKernel,
  killKernel,
  launchKernel,
  pasteCell,
  save,
  saveAs,
  setCursorBlink,
  setGithubToken,
  setTheme,
  toggleOutputExpansion
} from "@nteract/core/actions";

import { defaultPathFallback, cwdKernelFallback } from "./path";

export function dispatchSaveAs(store, evt, filename) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  store.dispatch(saveAs(filename, notebook));
}

const dialog = remote.dialog;

export function showSaveAsDialog() {
  return new Promise((resolve, reject) => {
    const opts = Object.assign(
      {
        title: "Save Notebook",
        filters: [{ name: "Notebooks", extensions: ["ipynb"] }]
      },
      defaultPathFallback()
    );

    const filename = dialog.showSaveDialog(opts);

    if (filename && path.extname(filename) === "") {
      resolve(`${filename}.ipynb`);
    }
    if (filename === undefined) {
      reject();
    }
    resolve(filename);
  });
}

export function triggerWindowRefresh(store, filename) {
  if (!filename) {
    return;
  }
  const state = store.getState();
  const notebook = state.document.get("notebook");
  store.dispatch(saveAs(filename, notebook));
}

export function dispatchRestartKernel(store) {
  const state = store.getState();
  const notificationSystem = state.app.get("notificationSystem");

  let cwd = cwdKernelFallback();
  if (state && state.document && state.document.get("filename")) {
    cwd = path.dirname(path.resolve(state.document.filename));
  }

  store.dispatch(killKernel);
  store.dispatch(launchKernel(state.app.kernelSpec, cwd));

  notificationSystem.addNotification({
    title: "Kernel Restarted",
    message: `Kernel ${state.app.kernelSpecDisplayName} has been restarted.`,
    dismissible: true,
    position: "tr",
    level: "success"
  });
}

export function triggerKernelRefresh(store) {
  return new Promise(resolve => {
    dialog.showMessageBox(
      {
        type: "question",
        buttons: ["Launch New Kernel", "Don't Launch New Kernel"],
        title: "New Kernel Needs to Be Launched",
        message:
          "It looks like you've saved your notebook file to a new location.",
        detail:
          "The kernel executing your code thinks your notebook is still in the " +
          "old location. Would you like to launch a new kernel to match it with the " +
          "new location of the notebook?"
      },
      index => {
        if (index === 0) {
          dispatchRestartKernel(store);
        }
        resolve();
      }
    );
  });
}

export function triggerSaveAs(store) {
  showSaveAsDialog().then(filename => {
    triggerWindowRefresh(store, filename);
    triggerKernelRefresh(store);
  });
}

export function dispatchSave(store) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  const filename = state.document.get("filename");
  if (!filename) {
    triggerSaveAs(store);
  } else {
    store.dispatch(save(filename, notebook));
  }
}

export function dispatchNewKernel(store, evt, spec) {
  const state = store.getState();
  let cwd = cwdKernelFallback();
  if (state && state.document && state.document.get("filename")) {
    cwd = path.dirname(path.resolve(state.document.get("filename")));
  }
  store.dispatch(launchKernel(spec, cwd));
}

export function dispatchPublishAnonGist(store) {
  store.dispatch({ type: "PUBLISH_ANONYMOUS_GIST" });
}

export function dispatchPublishUserGist(store, event, githubToken) {
  if (githubToken) {
    store.dispatch(setGithubToken(githubToken));
  }
  store.dispatch({ type: "PUBLISH_USER_GIST" });
}

/**
 * Redux dispatch function to run the focused cell and all cells below it.
 * It obtains the focused cell cell id and all code cell cell ids below.
 * It dispatches the {@link executeCell} action on all of those retrieved cells.
 *
 * @exports
 * @param {Object} store - The Redux store
 */
export function dispatchRunAllBelow(store) {
  const state = store.getState();
  const focusedCellId = state.document.get("cellFocused");
  const notebook = state.document.get("notebook");
  const indexOfFocusedCell = notebook.get("cellOrder").indexOf(focusedCellId);
  const cellsBelowFocusedId = notebook
    .get("cellOrder")
    .skip(indexOfFocusedCell);
  const cells = notebook.get("cellMap");

  cellsBelowFocusedId
    .filter(cellID => cells.getIn([cellID, "cell_type"]) === "code")
    .map(cellID =>
      store.dispatch(executeCell(cellID, cells.getIn([cellID, "source"])))
    );
}

export function dispatchRunAll(store) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  const cells = notebook.get("cellMap");
  notebook
    .get("cellOrder")
    .filter(cellID => cells.getIn([cellID, "cell_type"]) === "code")
    .map(cellID =>
      store.dispatch(executeCell(cellID, cells.getIn([cellID, "source"])))
    );
}

export function dispatchClearAll(store) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  notebook.get("cellOrder").map(value => store.dispatch(clearOutputs(value)));
}

export function dispatchUnhideAll(store) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  const cells = notebook.get("cellMap");
  notebook
    .get("cellOrder")
    .filter(cellID => cells.getIn([cellID, "metadata", "inputHidden"]))
    .map(cellID => store.dispatch(toggleCellInputVisibility(cellID)));
}

export function dispatchKillKernel(store) {
  store.dispatch(killKernel);
}

export function dispatchInterruptKernel(store) {
  const state = store.getState();
  const notificationSystem = state.app.get("notificationSystem");
  if (process.platform === "win32") {
    notificationSystem.addNotification({
      title: "Not supported in Windows",
      message: "Kernel interruption is currently not supported in Windows.",
      level: "error"
    });
  } else {
    store.dispatch(interruptKernel);
  }
}

export function dispatchRestartClearAll(store) {
  dispatchRestartKernel(store);
  dispatchClearAll(store);
}

export function dispatchZoomIn() {
  webFrame.setZoomLevel(webFrame.getZoomLevel() + 1);
}

export function dispatchZoomOut() {
  webFrame.setZoomLevel(webFrame.getZoomLevel() - 1);
}

export function dispatchZoomReset() {
  webFrame.setZoomLevel(0);
}

export function dispatchSetTheme(store, evt, theme) {
  store.dispatch(setTheme(theme));
}

export function dispatchSetCursorBlink(store, evt, value) {
  store.dispatch(setCursorBlink(value));
}

export function dispatchCopyCell(store) {
  const state = store.getState();
  const focused = state.document.get("cellFocused");
  store.dispatch(copyCell(focused));
}

export function dispatchCutCell(store) {
  const state = store.getState();
  const focused = state.document.get("cellFocused");
  store.dispatch(cutCell(focused));
}

export function dispatchPasteCell(store) {
  store.dispatch(pasteCell());
}

export function dispatchCreateCellAfter(store) {
  const state = store.getState();
  const focused = state.document.get("cellFocused");
  store.dispatch(createCellAfter("code", focused));
}

export function dispatchCreateTextCellAfter(store) {
  const state = store.getState();
  const focused = state.document.get("cellFocused");
  store.dispatch(createCellAfter("markdown", focused));
}

export function dispatchLoad(store, event, filename) {
  store.dispatch(load(filename));
}

export function dispatchNewNotebook(store, event, kernelSpec) {
  store.dispatch(newNotebook(kernelSpec, cwdKernelFallback()));
}

/**
 * Print the current notebook to PDF.
 * It will expand all cell outputs before printing and restore cells it expanded when complete.
 *
 * @param {object} store - The Redux store
 * @param {string} filename - filename of PDF to be saved.
 * @param {any} notificationSystem - reference to global notification system
 */
export function exportPDF(
  store: object,
  filename: string,
  notificationSystem
): void {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  const cellMap = notebook.get("cellMap");
  const cellOrder = notebook.get("cellOrder");
  const unexpandedCells = cellOrder.filter(
    cellID => cellMap.getIn([cellID, "metadata", "outputHidden"]) === false
  );

  // Expand unexpanded cells
  unexpandedCells.map(cellID => store.dispatch(toggleOutputExpansion(cellID)));

  remote.getCurrentWindow().webContents.printToPDF(
    {
      printBackground: true
    },
    (error, data) => {
      if (error) throw error;

      // Restore the modified cells to their unexpanded state.
      unexpandedCells.map(cellID =>
        store.dispatch(toggleOutputExpansion(cellID))
      );

      fs.writeFile(`${filename}.pdf`, data, error_fs => {
        notificationSystem.addNotification({
          title: "PDF exported",
          message: `Notebook ${filename} has been exported as a pdf.`,
          dismissible: true,
          position: "tr",
          level: "success",
          action: {
            label: "Open PDF",
            callback: function openPDF() {
              shell.openItem(`${filename}.pdf`);
            }
          }
        });
      });
    }
  );
}

export function triggerSaveAsPDF(store) {
  showSaveAsDialog()
    .then(filename =>
      Promise.all([
        triggerWindowRefresh(store, filename),
        triggerKernelRefresh(store)
      ])
    )
    .then(() => storeToPDF(store))
    .catch(e =>
      store.dispatch({ type: "ERROR", payload: e.message, error: true })
    );
}

export function storeToPDF(store) {
  const state = store.getState();
  let filename = path.basename(state.document.get("filename"), ".ipynb");
  const notificationSystem = state.app.get("notificationSystem");
  if (filename === "") {
    notificationSystem.addNotification({
      title: "File has not been saved!",
      message: [
        "Click the button below to save the notebook such that it can be ",
        "exported as a PDF."
      ],
      dismissible: true,
      position: "tr",
      level: "warning",
      action: {
        label: "Save As",
        callback: function cb() {
          triggerSaveAsPDF(store);
        }
      }
    });
  } else {
    filename = path.join(
      path.dirname(state.document.get("filename")),
      filename
    );
    exportPDF(store, filename, notificationSystem);
  }
}

export function dispatchLoadConfig(store) {
  store.dispatch(loadConfig());
}

export function initMenuHandlers(store) {
  ipc.on("main:new", dispatchNewNotebook.bind(null, store));
  ipc.on("menu:new-kernel", dispatchNewKernel.bind(null, store));
  ipc.on("menu:run-all", dispatchRunAll.bind(null, store));
  ipc.on("menu:run-all-below", dispatchRunAllBelow.bind(null, store));
  ipc.on("menu:clear-all", dispatchClearAll.bind(null, store));
  ipc.on("menu:unhide-all", dispatchUnhideAll.bind(null, store));
  ipc.on("menu:save", throttle(dispatchSave.bind(null, store), 2000));
  ipc.on("menu:save-as", dispatchSaveAs.bind(null, store));
  ipc.on("menu:new-code-cell", dispatchCreateCellAfter.bind(null, store));
  ipc.on("menu:new-text-cell", dispatchCreateTextCellAfter.bind(null, store));
  ipc.on("menu:copy-cell", dispatchCopyCell.bind(null, store));
  ipc.on("menu:cut-cell", dispatchCutCell.bind(null, store));
  ipc.on("menu:paste-cell", dispatchPasteCell.bind(null, store));
  ipc.on("menu:kill-kernel", dispatchKillKernel.bind(null, store));
  ipc.on("menu:interrupt-kernel", dispatchInterruptKernel.bind(null, store));
  ipc.on("menu:restart-kernel", dispatchRestartKernel.bind(null, store));
  ipc.on(
    "menu:restart-and-clear-all",
    dispatchRestartClearAll.bind(null, store)
  );
  ipc.on("menu:publish:gist", dispatchPublishAnonGist.bind(null, store));
  ipc.on("menu:zoom-in", dispatchZoomIn.bind(null, store));
  ipc.on("menu:zoom-out", dispatchZoomOut.bind(null, store));
  ipc.on("menu:zoom-reset", dispatchZoomReset.bind(null, store));
  ipc.on("menu:theme", dispatchSetTheme.bind(null, store));
  ipc.on("menu:set-blink-rate", dispatchSetCursorBlink.bind(null, store));
  ipc.on("menu:github:auth", dispatchPublishUserGist.bind(null, store));
  ipc.on("menu:exportPDF", storeToPDF.bind(null, store));
  // OCD: This is more like the registration of main -> renderer thread
  ipc.on("main:load", dispatchLoad.bind(null, store));
  ipc.on("main:load-config", dispatchLoadConfig.bind(null, store));
}
<commit_msg>fix kernel restart on desktop<commit_after>/* eslint-disable no-unused-vars, no-use-before-define */
import { ipcRenderer as ipc, webFrame, remote, shell } from "electron";

import * as path from "path";

import * as fs from "fs";

import { throttle } from "lodash";

import { load, newNotebook } from "@nteract/core/actions";

import { loadConfig } from "@nteract/core/actions";

import {
  toggleCellInputVisibility,
  clearOutputs,
  copyCell,
  createCellAfter,
  cutCell,
  executeCell,
  interruptKernel,
  killKernel,
  launchKernel,
  launchKernelByName,
  pasteCell,
  save,
  saveAs,
  setCursorBlink,
  setGithubToken,
  setTheme,
  toggleOutputExpansion
} from "@nteract/core/actions";

import { defaultPathFallback, cwdKernelFallback } from "./path";

export function dispatchSaveAs(store, evt, filename) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  store.dispatch(saveAs(filename, notebook));
}

const dialog = remote.dialog;

export function showSaveAsDialog() {
  return new Promise((resolve, reject) => {
    const opts = Object.assign(
      {
        title: "Save Notebook",
        filters: [{ name: "Notebooks", extensions: ["ipynb"] }]
      },
      defaultPathFallback()
    );

    const filename = dialog.showSaveDialog(opts);

    if (filename && path.extname(filename) === "") {
      resolve(`${filename}.ipynb`);
    }
    if (filename === undefined) {
      reject();
    }
    resolve(filename);
  });
}

export function triggerWindowRefresh(store, filename) {
  if (!filename) {
    return;
  }
  const state = store.getState();
  const notebook = state.document.get("notebook");
  store.dispatch(saveAs(filename, notebook));
}

export function dispatchRestartKernel(store) {
  // TODO: Make this an action to dispatch that an epic consumes, which will stop the
  //       current kernel and launch a new kernel of the same type
  const state = store.getState();
  const notificationSystem = state.app.notificationSystem;

  let cwd = cwdKernelFallback();
  if (state && state.document && state.document.get("filename")) {
    cwd = path.dirname(path.resolve(state.document.filename));
  }

  store.dispatch(killKernel);
  // TODO: Use the kernelspec directly, requires us having the kernelspecs available
  //       in the store.
  const kernelName =
    state && state.app && state.app.kernel && state.app.kernel.kernelSpecName
      ? state.app.kernel.kernelSpecName
      : null;

  if (!kernelName) {
    notificationSystem.addNotification({
      title: "Failure to Restart",
      message: `Unable to restart kernel, please select a new kernel.`,
      dismissible: true,
      position: "tr",
      level: "error"
    });

    return;
  }
  store.dispatch(launchKernelByName(kernelName, cwd));

  notificationSystem.addNotification({
    title: "Kernel Restarted",
    message: `Kernel ${state.app.kernel.kernelSpecName} has been restarted.`,
    dismissible: true,
    position: "tr",
    level: "success"
  });
}

export function triggerKernelRefresh(store) {
  return new Promise(resolve => {
    dialog.showMessageBox(
      {
        type: "question",
        buttons: ["Launch New Kernel", "Don't Launch New Kernel"],
        title: "New Kernel Needs to Be Launched",
        message:
          "It looks like you've saved your notebook file to a new location.",
        detail:
          "The kernel executing your code thinks your notebook is still in the " +
          "old location. Would you like to launch a new kernel to match it with the " +
          "new location of the notebook?"
      },
      index => {
        if (index === 0) {
          dispatchRestartKernel(store);
        }
        resolve();
      }
    );
  });
}

export function triggerSaveAs(store) {
  showSaveAsDialog().then(filename => {
    triggerWindowRefresh(store, filename);
    triggerKernelRefresh(store);
  });
}

export function dispatchSave(store) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  const filename = state.document.get("filename");
  if (!filename) {
    triggerSaveAs(store);
  } else {
    store.dispatch(save(filename, notebook));
  }
}

export function dispatchNewKernel(store, evt, spec) {
  const state = store.getState();
  let cwd = cwdKernelFallback();
  if (state && state.document && state.document.get("filename")) {
    cwd = path.dirname(path.resolve(state.document.get("filename")));
  }
  store.dispatch(launchKernel(spec, cwd));
}

export function dispatchPublishAnonGist(store) {
  store.dispatch({ type: "PUBLISH_ANONYMOUS_GIST" });
}

export function dispatchPublishUserGist(store, event, githubToken) {
  if (githubToken) {
    store.dispatch(setGithubToken(githubToken));
  }
  store.dispatch({ type: "PUBLISH_USER_GIST" });
}

/**
 * Redux dispatch function to run the focused cell and all cells below it.
 * It obtains the focused cell cell id and all code cell cell ids below.
 * It dispatches the {@link executeCell} action on all of those retrieved cells.
 *
 * @exports
 * @param {Object} store - The Redux store
 */
export function dispatchRunAllBelow(store) {
  const state = store.getState();
  const focusedCellId = state.document.get("cellFocused");
  const notebook = state.document.get("notebook");
  const indexOfFocusedCell = notebook.get("cellOrder").indexOf(focusedCellId);
  const cellsBelowFocusedId = notebook
    .get("cellOrder")
    .skip(indexOfFocusedCell);
  const cells = notebook.get("cellMap");

  cellsBelowFocusedId
    .filter(cellID => cells.getIn([cellID, "cell_type"]) === "code")
    .map(cellID =>
      store.dispatch(executeCell(cellID, cells.getIn([cellID, "source"])))
    );
}

export function dispatchRunAll(store) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  const cells = notebook.get("cellMap");
  notebook
    .get("cellOrder")
    .filter(cellID => cells.getIn([cellID, "cell_type"]) === "code")
    .map(cellID =>
      store.dispatch(executeCell(cellID, cells.getIn([cellID, "source"])))
    );
}

export function dispatchClearAll(store) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  notebook.get("cellOrder").map(value => store.dispatch(clearOutputs(value)));
}

export function dispatchUnhideAll(store) {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  const cells = notebook.get("cellMap");
  notebook
    .get("cellOrder")
    .filter(cellID => cells.getIn([cellID, "metadata", "inputHidden"]))
    .map(cellID => store.dispatch(toggleCellInputVisibility(cellID)));
}

export function dispatchKillKernel(store) {
  store.dispatch(killKernel);
}

export function dispatchInterruptKernel(store) {
  const state = store.getState();
  const notificationSystem = state.app.get("notificationSystem");
  if (process.platform === "win32") {
    notificationSystem.addNotification({
      title: "Not supported in Windows",
      message: "Kernel interruption is currently not supported in Windows.",
      level: "error"
    });
  } else {
    store.dispatch(interruptKernel);
  }
}

export function dispatchRestartClearAll(store) {
  dispatchRestartKernel(store);
  dispatchClearAll(store);
}

export function dispatchZoomIn() {
  webFrame.setZoomLevel(webFrame.getZoomLevel() + 1);
}

export function dispatchZoomOut() {
  webFrame.setZoomLevel(webFrame.getZoomLevel() - 1);
}

export function dispatchZoomReset() {
  webFrame.setZoomLevel(0);
}

export function dispatchSetTheme(store, evt, theme) {
  store.dispatch(setTheme(theme));
}

export function dispatchSetCursorBlink(store, evt, value) {
  store.dispatch(setCursorBlink(value));
}

export function dispatchCopyCell(store) {
  const state = store.getState();
  const focused = state.document.get("cellFocused");
  store.dispatch(copyCell(focused));
}

export function dispatchCutCell(store) {
  const state = store.getState();
  const focused = state.document.get("cellFocused");
  store.dispatch(cutCell(focused));
}

export function dispatchPasteCell(store) {
  store.dispatch(pasteCell());
}

export function dispatchCreateCellAfter(store) {
  const state = store.getState();
  const focused = state.document.get("cellFocused");
  store.dispatch(createCellAfter("code", focused));
}

export function dispatchCreateTextCellAfter(store) {
  const state = store.getState();
  const focused = state.document.get("cellFocused");
  store.dispatch(createCellAfter("markdown", focused));
}

export function dispatchLoad(store, event, filename) {
  store.dispatch(load(filename));
}

export function dispatchNewNotebook(store, event, kernelSpec) {
  store.dispatch(newNotebook(kernelSpec, cwdKernelFallback()));
}

/**
 * Print the current notebook to PDF.
 * It will expand all cell outputs before printing and restore cells it expanded when complete.
 *
 * @param {object} store - The Redux store
 * @param {string} filename - filename of PDF to be saved.
 * @param {any} notificationSystem - reference to global notification system
 */
export function exportPDF(
  store: object,
  filename: string,
  notificationSystem
): void {
  const state = store.getState();
  const notebook = state.document.get("notebook");
  const cellMap = notebook.get("cellMap");
  const cellOrder = notebook.get("cellOrder");
  const unexpandedCells = cellOrder.filter(
    cellID => cellMap.getIn([cellID, "metadata", "outputHidden"]) === false
  );

  // Expand unexpanded cells
  unexpandedCells.map(cellID => store.dispatch(toggleOutputExpansion(cellID)));

  remote.getCurrentWindow().webContents.printToPDF(
    {
      printBackground: true
    },
    (error, data) => {
      if (error) throw error;

      // Restore the modified cells to their unexpanded state.
      unexpandedCells.map(cellID =>
        store.dispatch(toggleOutputExpansion(cellID))
      );

      fs.writeFile(`${filename}.pdf`, data, error_fs => {
        notificationSystem.addNotification({
          title: "PDF exported",
          message: `Notebook ${filename} has been exported as a pdf.`,
          dismissible: true,
          position: "tr",
          level: "success",
          action: {
            label: "Open PDF",
            callback: function openPDF() {
              shell.openItem(`${filename}.pdf`);
            }
          }
        });
      });
    }
  );
}

export function triggerSaveAsPDF(store) {
  showSaveAsDialog()
    .then(filename =>
      Promise.all([
        triggerWindowRefresh(store, filename),
        triggerKernelRefresh(store)
      ])
    )
    .then(() => storeToPDF(store))
    .catch(e =>
      store.dispatch({ type: "ERROR", payload: e.message, error: true })
    );
}

export function storeToPDF(store) {
  const state = store.getState();
  let filename = path.basename(state.document.get("filename"), ".ipynb");
  const notificationSystem = state.app.get("notificationSystem");
  if (filename === "") {
    notificationSystem.addNotification({
      title: "File has not been saved!",
      message: [
        "Click the button below to save the notebook such that it can be ",
        "exported as a PDF."
      ],
      dismissible: true,
      position: "tr",
      level: "warning",
      action: {
        label: "Save As",
        callback: function cb() {
          triggerSaveAsPDF(store);
        }
      }
    });
  } else {
    filename = path.join(
      path.dirname(state.document.get("filename")),
      filename
    );
    exportPDF(store, filename, notificationSystem);
  }
}

export function dispatchLoadConfig(store) {
  store.dispatch(loadConfig());
}

export function initMenuHandlers(store) {
  ipc.on("main:new", dispatchNewNotebook.bind(null, store));
  ipc.on("menu:new-kernel", dispatchNewKernel.bind(null, store));
  ipc.on("menu:run-all", dispatchRunAll.bind(null, store));
  ipc.on("menu:run-all-below", dispatchRunAllBelow.bind(null, store));
  ipc.on("menu:clear-all", dispatchClearAll.bind(null, store));
  ipc.on("menu:unhide-all", dispatchUnhideAll.bind(null, store));
  ipc.on("menu:save", throttle(dispatchSave.bind(null, store), 2000));
  ipc.on("menu:save-as", dispatchSaveAs.bind(null, store));
  ipc.on("menu:new-code-cell", dispatchCreateCellAfter.bind(null, store));
  ipc.on("menu:new-text-cell", dispatchCreateTextCellAfter.bind(null, store));
  ipc.on("menu:copy-cell", dispatchCopyCell.bind(null, store));
  ipc.on("menu:cut-cell", dispatchCutCell.bind(null, store));
  ipc.on("menu:paste-cell", dispatchPasteCell.bind(null, store));
  ipc.on("menu:kill-kernel", dispatchKillKernel.bind(null, store));
  ipc.on("menu:interrupt-kernel", dispatchInterruptKernel.bind(null, store));
  ipc.on("menu:restart-kernel", dispatchRestartKernel.bind(null, store));
  ipc.on(
    "menu:restart-and-clear-all",
    dispatchRestartClearAll.bind(null, store)
  );
  ipc.on("menu:publish:gist", dispatchPublishAnonGist.bind(null, store));
  ipc.on("menu:zoom-in", dispatchZoomIn.bind(null, store));
  ipc.on("menu:zoom-out", dispatchZoomOut.bind(null, store));
  ipc.on("menu:zoom-reset", dispatchZoomReset.bind(null, store));
  ipc.on("menu:theme", dispatchSetTheme.bind(null, store));
  ipc.on("menu:set-blink-rate", dispatchSetCursorBlink.bind(null, store));
  ipc.on("menu:github:auth", dispatchPublishUserGist.bind(null, store));
  ipc.on("menu:exportPDF", storeToPDF.bind(null, store));
  // OCD: This is more like the registration of main -> renderer thread
  ipc.on("main:load", dispatchLoad.bind(null, store));
  ipc.on("main:load-config", dispatchLoadConfig.bind(null, store));
}
<|endoftext|>


<commit_before>var slackMsgs = require('./slackMsgs.js');
var url = require('url');
var Trello = require('node-trello');
var Promise = require('bluebird');
var mongo = require('mongoskin');

var uri = process.env.MONGODB_URI;
var trelloKey = process.env.HUBOT_TRELLO_KEY;
// promisify mongoskin with bluebird
Object.keys(mongo).forEach(function (key) {
    var value = mongo[key];
    if (typeof value === "function") {
        Promise.promisifyAll(value);
        Promise.promisifyAll(value.prototype);
    }
});
Promise.promisifyAll(mongo);
// connect to mLab database
var db = mongo.MongoClient.connect(uri);

var bcrypt = require('bcryptjs');
var request = require('request-promise');
var encryption = require('./encryption.js');

var app_key = process.env.HUBOT_TRELLO_KEY;
var oauth_secret = process.env.HUBOT_TRELLO_OAUTH;

module.exports = function (robot) {

    var oauth_secrets = {};
    var loginCallback = `https://andreasbot.herokuapp.com/hubot/trello-token`;
    var scope = 'read,write,account'
    var TrelloOAuth = require('./trello-oauth.js')
    var tOAuth = new TrelloOAuth(app_key, oauth_secret, loginCallback, 'Hubot', scope);

    robot.respond(/trello auth/, function (res) {
        let userId = res.message.user.id;
        tOAuth.getRequestToken(function (err, data) {
            oauth_secrets['username'] = res.message.user.name;
            oauth_secrets['id'] = res.message.user.id;
            oauth_secrets[data.oauth_token] = data.oauth_token_secret;

            res.reply(data.redirect);
        })
    })

    robot.router.get('/hubot/trello-token', function (req, res_r) {
        let args = req.query;
        let query = url.parse(req.url, true).query;
        let token = query.oauth_token;
        args['oauth_token_secret'] = oauth_secrets[token];
        tOAuth.getAccessToken(args, function (err, data) {
            if (err) throw err;
            let userName = oauth_secrets['username'];
            let userId = oauth_secrets['id'];
            let token = encryption.encrypt(data['oauth_access_token']); // encrypt token before storing it
            // TODO: encryption -> return promise
            // TODO: get trello username and save
            //TODO error
            var trelloUsername = data.username
            db.bind('users');
            db.users.findAndModify(
                { _id: userId },
                [["_id", 1]],
                { trello_token: token },
                { upsert: true },
                function (err, result) {
                    if (err) throw err;
                    if (result) {
                        robot.logger.info(`User's Token Added to DB!\n`, result)
                    };
                })

        })
        res_r.redirect('/a');
    });

    /**********************************************************/
    /* DEPRECATED */
    robot.respond(/trello get token/i, function (res_r) {

        let scope = 'read,write,account';
        let name = 'Hubot';
        let expr = '30days';
        let cb_method = 'fragment';
        let return_url = 'https://andreasbot.herokuapp.com/hubot/trello-token';
        let url = `https://trello.com/1/authorize?expiration=${expr}&name=${name}&scope=${scope}&key=${app_key}&response_type=token&callback_method=${cb_method}&return_url=${return_url}`;
        var msg = slackMsgs.basicMessage();

        msg.attachments[0].pretext = "Please get a token to authorize your Trello account";
        msg.attachments[0].title = "Trello Token";
        msg.attachments[0].title_link = url;
        msg.attachments[0].text = "Copy the token from the link above and run\n *trello add token <YOUR TOKEN>*";
        msg.attachments[0].footer = "Trello";
        msg.attachments[0].footer_icon = "https://d2k1ftgv7pobq7.cloudfront.net/meta/u/res/images/b428584f224c42e98d158dad366351b0/trello-mark-blue.png";
        res_r.send(msg);
    })

    /**********************************************************/
    /* DEPRECATED */
    robot.respond(/trello add token (.*)/i, function (res_r) {
        var token = res_r.match[1];
        //***IMPORTANT***
        // the .env assignment doesnt work with HEROKU!
        // must set up a heroku client and communicate through their api
        process.env['HUBOT_TRELLO_TOKEN'] = token;
    })
}<commit_msg>db - findAndModify5-push<commit_after>var slackMsgs = require('./slackMsgs.js');
var url = require('url');
var Trello = require('node-trello');
var Promise = require('bluebird');
var mongo = require('mongoskin');

var uri = process.env.MONGODB_URI;
var trelloKey = process.env.HUBOT_TRELLO_KEY;
// promisify mongoskin with bluebird
Object.keys(mongo).forEach(function (key) {
    var value = mongo[key];
    if (typeof value === "function") {
        Promise.promisifyAll(value);
        Promise.promisifyAll(value.prototype);
    }
});
Promise.promisifyAll(mongo);
// connect to mLab database
var db = mongo.MongoClient.connect(uri);

var bcrypt = require('bcryptjs');
var request = require('request-promise');
var encryption = require('./encryption.js');

var app_key = process.env.HUBOT_TRELLO_KEY;
var oauth_secret = process.env.HUBOT_TRELLO_OAUTH;

module.exports = function (robot) {

    var oauth_secrets = {};
    var loginCallback = `https://andreasbot.herokuapp.com/hubot/trello-token`;
    var scope = 'read,write,account'
    var TrelloOAuth = require('./trello-oauth.js')
    var tOAuth = new TrelloOAuth(app_key, oauth_secret, loginCallback, 'Hubot', scope);

    robot.respond(/trello auth/, function (res) {
        let userId = res.message.user.id;
        tOAuth.getRequestToken(function (err, data) {
            oauth_secrets['username'] = res.message.user.name;
            oauth_secrets['id'] = res.message.user.id;
            oauth_secrets[data.oauth_token] = data.oauth_token_secret;

            res.reply(data.redirect);
        })
    })

    robot.router.get('/hubot/trello-token', function (req, res_r) {
        let args = req.query;
        let query = url.parse(req.url, true).query;
        let token = query.oauth_token;
        args['oauth_token_secret'] = oauth_secrets[token];
        tOAuth.getAccessToken(args, function (err, data) {
            if (err) throw err;
            let userName = oauth_secrets['username'];
            let userId = oauth_secrets['id'];
            let token = encryption.encrypt(data['oauth_access_token']); // encrypt token before storing it
            // TODO: encryption -> return promise
            // TODO: get trello username and save
            //TODO error
            var trelloUsername = data.username
            db.bind('users');
            db.users.findAndModify(
                { _id: userId },
                [["_id", 1]],
                { $push: { trello_token: token } },
                { upsert: true },
                function (err, result) {
                    if (err) throw err;
                    if (result) {
                        robot.logger.info(`User's Token Added to DB!\n`, result)
                    };
                })

        })
        res_r.redirect('/a');
    });

    /**********************************************************/
    /* DEPRECATED */
    robot.respond(/trello get token/i, function (res_r) {

        let scope = 'read,write,account';
        let name = 'Hubot';
        let expr = '30days';
        let cb_method = 'fragment';
        let return_url = 'https://andreasbot.herokuapp.com/hubot/trello-token';
        let url = `https://trello.com/1/authorize?expiration=${expr}&name=${name}&scope=${scope}&key=${app_key}&response_type=token&callback_method=${cb_method}&return_url=${return_url}`;
        var msg = slackMsgs.basicMessage();

        msg.attachments[0].pretext = "Please get a token to authorize your Trello account";
        msg.attachments[0].title = "Trello Token";
        msg.attachments[0].title_link = url;
        msg.attachments[0].text = "Copy the token from the link above and run\n *trello add token <YOUR TOKEN>*";
        msg.attachments[0].footer = "Trello";
        msg.attachments[0].footer_icon = "https://d2k1ftgv7pobq7.cloudfront.net/meta/u/res/images/b428584f224c42e98d158dad366351b0/trello-mark-blue.png";
        res_r.send(msg);
    })

    /**********************************************************/
    /* DEPRECATED */
    robot.respond(/trello add token (.*)/i, function (res_r) {
        var token = res_r.match[1];
        //***IMPORTANT***
        // the .env assignment doesnt work with HEROKU!
        // must set up a heroku client and communicate through their api
        process.env['HUBOT_TRELLO_TOKEN'] = token;
    })
}<|endoftext|>


<commit_before>/**
 * A combination of players is a team. A team should contain at least one player *
 *
 * @return TeamModel
 * @author Erik E. Lorenz <erik@tuvero.de>
 * @license MIT License
 * @see LICENSE
 */

define(["lib/extend", "list/indexedmodel", "ui/playermodel", "core/type"], function (extend,
  IndexedModel, PlayerModel, Type) {

  /**
   * Constructor
   *
   * @param players
   *          an array of PlayerModel instances
   * @param id
   *          a preferably unique numeric team id
   */
  function TeamModel(players, id) {
    TeamModel.superconstructor.call(this, id);

    this.number = "";
    this.alias = "";
    this.club = "";
    this.email = "";
    this.elo = 0;
    this.rankingpoints = 0;
    this.players = [];

    this.setPlayers(players);
  }
  extend(TeamModel, IndexedModel);

  /**
   * .length represents the size of the team
   */
  TeamModel.prototype.length = 0;

  /**
   * retrieve a single player. For the number of players, see
   * TeamModel.prototype.length
   *
   * @param id
   *          the index of the player inside the team
   * @return a PlayerModel reference
   */
  TeamModel.prototype.getPlayer = function (id) {
    if (id >= 0 && id < this.length) {
      return this.players[id];
    }
    return undefined;
  };

  /**
   * DO NOT USE DIRECTLY (why not?)
   *
   * @param players
   *          an array of PlayerModel instances
   */
  TeamModel.prototype.setPlayers = function (players) {
    players = players || [];
    if (players.length === 0) {
      players.push(new PlayerModel());
    }
    this.length = players.length;
    this.players = players.slice(0);
    this.players.forEach(function (player) {
      player.registerListener(this);
    }, this);
  };

  TeamModel.prototype.getNames = function () {
    return this.players.map(function (player) {
      return player.getName();
    });
  };

  TeamModel.prototype.getNumber = function () {
    var number = this.number;

    if (number) {
      return number;
    }

    number = this.getID();
    if (Type.isNumber(number)) {
      return number + 1;
    }

    return number;
  };

  /**
   * Callback listener
   *
   * One of the player names was updated. This is passed through to the team
   * event emitter.
   *
   * @param emitter
   *          a PlayerModel instance
   * @param event
   *          the event type
   *
   */
  TeamModel.prototype.onupdate = function (emitter, event) {
    var data;
    data = {
      id: this.players.indexOf(emitter)
    };
    this.emit("update", data);
  };

  TeamModel.prototype.SAVEFORMAT = Object
    .create(TeamModel.superclass.SAVEFORMAT);
  TeamModel.prototype.SAVEFORMAT.p = [Object];
  // TeamModel.prototype.SAVEFORMAT.number = String;
  // TeamModel.prototype.SAVEFORMAT.alias = String;
  // TeamModel.prototype.SAVEFORMAT.club = String;
  // TeamModel.prototype.SAVEFORMAT.email = String;
  // TeamModel.prototype.SAVEFORMAT.elo = Number;
  // TeamModel.prototype.SAVEFORMAT.rankingpoints = Number;

  /**
   * prepares a serializable data object, which can later be used for restoring
   * the current state using the restore() function
   *
   * @return a serializable data object, which can be used for restoring
   */
  TeamModel.prototype.save = function () {
    var data = TeamModel.superclass.save.call(this);

    data.p = this.players.map(function (player) {
      return player.save();
    });

    if (this.number) {
      data.number = this.number;
    }

    if (this.alias) {
      data.alias = this.alias;
    }

    if (this.club) {
      data.club = this.club;
    }

    if (this.email) {
      data.email = this.email;
    }

    if (this.elo) {
      data.elo = this.elo;
    }

    if (this.rankingpoints) {
      data.rankingpoints = this.rankingpoints;
    }

    return data;
  };

  /**
   * restore a previously saved state from a serializable data object
   *
   * @param data
   *          a data object, that was previously written by save()
   * @return true on success, false otherwise
   */
  TeamModel.prototype.restore = function (data) {
    if (!TeamModel.superclass.restore.call(this, data)) {
      return false;
    }

    this.setPlayers(data.p.map(function (player) {
      var p = new PlayerModel();
      p.restore(player);
      return p;
    }));

    if (data.number) {
      this.number = data.number;
    }

    if (data.alias) {
      this.alias = data.alias;
    }

    if (data.club) {
      this.club = data.club;
    }

    if (data.email) {
      this.email = data.email;
    }

    if (data.elo) {
      this.elo = Number(data.elo);
    }

    if (data.rankingpoints) {
      this.rankingpoints = Number(data.rankingpoints);
    }

    return true;
  };

  return TeamModel;
});<commit_msg>Add TeamModel.prototype.updateRankingPointSum<commit_after>/**
 * A combination of players is a team. A team should contain at least one player *
 *
 * @return TeamModel
 * @author Erik E. Lorenz <erik@tuvero.de>
 * @license MIT License
 * @see LICENSE
 */

define(["lib/extend", "list/indexedmodel", "ui/playermodel", "core/type"], function (extend,
  IndexedModel, PlayerModel, Type) {

  /**
   * Constructor
   *
   * @param players
   *          an array of PlayerModel instances
   * @param id
   *          a preferably unique numeric team id
   */
  function TeamModel(players, id) {
    TeamModel.superconstructor.call(this, id);

    this.number = "";
    this.alias = "";
    this.club = "";
    this.email = "";
    this.elo = 0;
    this.rankingpoints = 0;
    this.players = [];

    this.setPlayers(players);
  }
  extend(TeamModel, IndexedModel);

  /**
   * .length represents the size of the team
   */
  TeamModel.prototype.length = 0;

  /**
   * retrieve a single player. For the number of players, see
   * TeamModel.prototype.length
   *
   * @param id
   *          the index of the player inside the team
   * @return a PlayerModel reference
   */
  TeamModel.prototype.getPlayer = function (id) {
    if (id >= 0 && id < this.length) {
      return this.players[id];
    }
    return undefined;
  };

  /**
   * DO NOT USE DIRECTLY (why not?)
   *
   * @param players
   *          an array of PlayerModel instances
   */
  TeamModel.prototype.setPlayers = function (players) {
    players = players || [];
    if (players.length === 0) {
      players.push(new PlayerModel());
    }
    this.length = players.length;
    this.players = players.slice(0);
    this.players.forEach(function (player) {
      player.registerListener(this);
    }, this);
  };

  TeamModel.prototype.getNames = function () {
    return this.players.map(function (player) {
      return player.getName();
    });
  };

  TeamModel.prototype.getNumber = function () {
    var number = this.number;

    if (number) {
      return number;
    }

    number = this.getID();
    if (Type.isNumber(number)) {
      return number + 1;
    }

    return number;
  };

  /**
   * Callback listener
   *
   * One of the player names was updated. This is passed through to the team
   * event emitter.
   *
   * @param emitter
   *          a PlayerModel instance
   * @param event
   *          the event type
   *
   */
  TeamModel.prototype.onupdate = function (emitter, event) {
    var data;
    data = {
      id: this.players.indexOf(emitter)
    };
    this.emit("update", data);
  };

  TeamModel.prototype.SAVEFORMAT = Object
    .create(TeamModel.superclass.SAVEFORMAT);
  TeamModel.prototype.SAVEFORMAT.p = [Object];
  // TeamModel.prototype.SAVEFORMAT.number = String;
  // TeamModel.prototype.SAVEFORMAT.alias = String;
  // TeamModel.prototype.SAVEFORMAT.club = String;
  // TeamModel.prototype.SAVEFORMAT.email = String;
  // TeamModel.prototype.SAVEFORMAT.elo = Number;
  // TeamModel.prototype.SAVEFORMAT.rankingpoints = Number;

  TeamModel.prototype.updateRankingPointSum = function () {
    this.rankingpoints = this.players.map(function (player) {
      return player.rankingpoints;
    }).reduce(function (a, b) {
      return a + b;
    }, 0);

    this.emit("update");
  };

  /**
   * prepares a serializable data object, which can later be used for restoring
   * the current state using the restore() function
   *
   * @return a serializable data object, which can be used for restoring
   */
  TeamModel.prototype.save = function () {
    var data = TeamModel.superclass.save.call(this);

    data.p = this.players.map(function (player) {
      return player.save();
    });

    if (this.number) {
      data.number = this.number;
    }

    if (this.alias) {
      data.alias = this.alias;
    }

    if (this.club) {
      data.club = this.club;
    }

    if (this.email) {
      data.email = this.email;
    }

    if (this.elo) {
      data.elo = this.elo;
    }

    if (this.rankingpoints) {
      data.rankingpoints = this.rankingpoints;
    }

    return data;
  };

  /**
   * restore a previously saved state from a serializable data object
   *
   * @param data
   *          a data object, that was previously written by save()
   * @return true on success, false otherwise
   */
  TeamModel.prototype.restore = function (data) {
    if (!TeamModel.superclass.restore.call(this, data)) {
      return false;
    }

    this.setPlayers(data.p.map(function (player) {
      var p = new PlayerModel();
      p.restore(player);
      return p;
    }));

    if (data.number) {
      this.number = data.number;
    }

    if (data.alias) {
      this.alias = data.alias;
    }

    if (data.club) {
      this.club = data.club;
    }

    if (data.email) {
      this.email = data.email;
    }

    if (data.elo) {
      this.elo = Number(data.elo);
    }

    if (data.rankingpoints) {
      this.rankingpoints = Number(data.rankingpoints);
    }

    return true;
  };

  return TeamModel;
});<|endoftext|>