<commit_before>
	$(document).ready(function() {
		$('#popup-nav-overview').click(function(){ popup_nav('overview'); });
		$('#popup-nav-hosts').click(function(){ popup_nav('hosts'); });
		$('#popup-nav-services').click(function(){ popup_nav('services'); });
		$('#popup-nav-about').click(function(){ popup_nav('about'); });

		popup_nav('overview');

		$('#popup-tab-hosts-filter').on('keyup', function() { popup_nav('hosts'); });
		$('#popup-tab-services-filter').on('keyup', function() { popup_nav('services'); });
	});

	table_classes = {
		'UP': 'success',
		'DOWN': 'danger',
		'UNREACHABLE': 'info',
		'OK': 'success',
		'WARNING': 'warning',
		'UNKNOWN': 'active',
		'CRITICAL': 'danger'
	};

	function popup_nav(to) {
		$('#popup-nav li').each(function(){ $(this).removeClass('active'); });
		$('#popup-nav-'+to).parent().addClass('active');

		$('.popup-tab').each(function(){ $(this).hide(); });
		$('#popup-tab-'+to).show();

		switch(to) {
			case 'services':
				chrome.extension.sendRequest({ request: 'data' }, function(e) {
					$('#popup-tab-services-tables').empty();

					if (e.state == 'ok') {
						var instances = icinga_get_instances();

						// Go through active instances
						for(i=0; i<instances.length; i++) {
							var instance = instances[i];
							instance_line = '';

							if (instance.active) {
								// Go through all hosts and check instance
								$.each(Object.keys(e.hosts).sort(), function(h_i,h) {
									var host = e.hosts[h];
									if (host.instance == i) {
										// Host HTML Line
										host_line = '
'+host.name+'		'+host.status+'
';
										service_line = '';

										// Go through all services
										$.each(Object.keys(host.services).sort(), function(s_i,s) {
											var service = host.services[s];

											var add_service = false;
											if ($('#popup-tab-services-filter').val()) {
												var reg = new RegExp($('#popup-tab-services-filter').val(), "i");
												if (reg.test(service.name))
													add_service = true;
											} else {
												add_service = true;
											}

											// Service HTML Line
											if (add_service) {
												switch (instance.icinga_type) {
													default: var service_name = ''+service.name+''; break;
													case 'icinga2_api': if (instance.url_web) { var service_name = ''+service.name+''; } else { var service_name = service.name; } break;
												}
												service_line += '
	'+service_name+'	'+service.status+'
';
											}
										});

										// If there is a service line OR host status down, add host line and append service lines
										if (service_line != '') {
											instance_line += host_line+service_line;
										}

										delete host_line;
										delete service_line;
									}
								});

								// Insert table
								if (instance_line) {
									$('#popup-tab-services-tables').append(''
										+ '
'
											+ '
'+instance.title+'
'
											+ '
'
												+ '
'
													+ 'Host	'
													+ 'Service	'
													+ 'Status	'
													//+ '	'
												+ '
'
											+ '
'
											+ '
'
												+ instance_line
											+ '
'
										+ '
'
									);
								}

								delete instance_line;
							}
						}
					} else {
						$('#popup-tab-hosts-tables').html('An error occured - could not connect with background task.');
					}
				});
			break;

			case 'hosts':
				chrome.extension.sendRequest({ request: 'data' }, function(e) {
					$('#popup-tab-hosts-tables').empty();

					if (e.state == 'ok') {
						var instances = icinga_get_instances();

						// Go through active instances
						for(i=0; i<instances.length; i++) {
							var instance = instances[i];
							instance_line = '';

							if (instance.active) {
								// Go through all hosts and check instance
								$.each(Object.keys(e.hosts).sort(), function(h_i,h) {
									var host = e.hosts[h];
									if (host.instance == i) {
										// regexp check filter
										var add_host = false;
										if ($('#popup-tab-hosts-filter').val()) {
											var reg = new RegExp($('#popup-tab-hosts-filter').val(), "i");
											if (reg.test(host.name))
												add_host = true;
										} else {
											add_host = true;
										}

										if (add_host) {
											// Host HTML Line
											switch (instance.icinga_type) {
												default: var host_name = ''+host.name+''; break;
												case 'icinga2_api': if (instance.url_web) { var host_name = ''+host.name+''; } else { var host_name = host.name; } break;
											}
											host_line = '
'+host_name+'	'+host.status+'
';
											instance_line += host_line;
										}

										delete host_line;
									}
								});

								// Insert table
								if (instance_line) {
									$('#popup-tab-hosts-tables').append(''
										+ '
'
											+ '
'+instance.title+'
'
											+ '
'
												+ '
'
													+ 'Host	'
													+ 'Status	'
												+ '
'
											+ '
'
											+ '
'
												+ instance_line
											+ '
'
										+ '
'
									);
								}

								delete instance_line;
							}
						}
					} else {
						$('#popup-tab-hosts-tables').html('An error occured - could not connect with background task.');
					}
				});
			break;

			case 'overview':
				chrome.extension.sendRequest({ request: 'data' }, function(e) {
					$('#popup-tab-overview-table').find('tbody').empty();
					$('#popup-tab-overview-downs').empty();
					$('#popup-tab-overview .alert').each(function(){ $(this).hide(); });

					if (e.state == 'ok') {
						var instances = icinga_get_instances();

						var worst_status = 0;

						// Go through active instances
						for(i=0; i<instances.length; i++) {
							var instance = instances[i];
							var counter_total = { hosts: 0, services: 0 };
							var counter_hosts = { up: 0, down: 0, unr: 0 };
							var counter_services = { ok: 0, warn: 0, unkn: 0, crit: 0 };
							var errors = '';

							if (instance.active && !instance.error) {
								instance_line = '';

								// Go through all hosts and check instance
								$.each(Object.keys(e.hosts), function(h_i,h) {
									var host = e.hosts[h];
									if (host.instance == i) {
										counter_total.hosts += 1;

										// Possible DOWN UNREACHABLE UP
										switch(host.status) {
											case 'UP': counter_hosts.up += 1; break;
											case 'DOWN': counter_hosts.down += 1; break;
											case 'UNREACHABLE': counter_hosts.unr += 1; break;
										}

										// Host HTML Line
										switch (instance.icinga_type) {
											default: var host_name = ''+host.name+''; break;
											case 'icinga2_api': if (instance.url_web) { var host_name = ''+host.name+''; } else { var host_name = host.name; } break;
										}
										host_line = '
'+host_name+'		'+host.status+'
';
										service_line = '';

										// Go through all services
										$.each(Object.keys(host.services), function(s_i,s) {
											var service = host.services[s];
											counter_total.services += 1;

											// Possible OK WARNING UNKNOWN CRITICAL
											switch(service.status) {
												case 'OK': counter_services.ok += 1; break;
												case 'WARNING': counter_services.warn += 1; break;
												case 'UNKNOWN': counter_services.unkn += 1; break;
												case 'CRITICAL': counter_services.crit += 1; break;
											}

											// Service HTML Line
											if (service.status == 'WARNING' || service.status == 'CRITICAL') {
												switch (instance.icinga_type) {
													default: var service_name = ''+service.name+''; break;
													case 'icinga2_api': if (instance.url_web) { var service_name = ''+service.name+''; } else { var service_name = service.name; } break;
												}
												service_line += '
	'+service_name+'	'+service.status+'
';
											}
										});

										// If there is a service line OR host status down, add host line and append service lines
										if (host.status == 'DOWN' || host.status == 'UNREACHABLE' || service_line != '') {
											instance_line += host_line+service_line;
										}

										delete host_line;
										delete service_line;
									}
								});

								// Build hosts column
								host_column = '';
								if (counter_hosts.up) host_column += ''+counter_hosts.up+' ';
								if (counter_hosts.down) host_column += ''+counter_hosts.down+' ';
								if (counter_hosts.unr) host_column += ''+counter_hosts.unr+' ';

								// Build services column
								service_column = '';
								if (counter_services.ok) service_column += ''+counter_services.ok+' ';
								if (counter_services.warn) service_column += ''+counter_services.warn+' ';
								if (counter_services.crit) service_column += ''+counter_services.crit+' ';
								if (counter_services.unkn) service_column += ''+counter_services.unkn+' ';

								// Insert into table
								$('#popup-tab-overview-table').find('tbody').append('
'
								+ ''+instance.title+'	'
								+ ''+host_column+'	'
								+ ''+service_column+'	'
								+ '
');

								// Update worst status
								if (counter_services.crit || counter_hosts.down || counter_hosts.unr) {
									var worst_status = 2;
								} else if (counter_services.warn && worst_status == 0) {
									var worst_status = 1;
								}

								// Error table
								if (instance_line) {
									$('#popup-tab-overview-downs').append(''
										+ '
'
											+ '
'+instance.title+'
'
											+ '
'
												+ '
'
													+ 'Host	'
													+ 'Service	'
													+ 'Status	'
													//+ '	'
												+ '
'
											+ '
'
											+ '
'
												+ instance_line
											+ '
'
										+ '
'
									);
								}

								delete host_column;
								delete service_column;
								delete instance_line;

							} else if (instance.active && instance.error) {
								// Insert into table
								$('#popup-tab-overview-table').find('tbody').append('
'
								+ ''+instance.title+'	'
								+ ''+instance.status_last+'	'
								+ '
');
							}

							delete counter_total;
							delete counter_hosts;
							delete counter_services;
							delete instance;
						}

						// Update alert according to worst status
						if (instances.length == 0) {
							$('#popup-tab-overview-alert-new').show();
						} else {
							$('#popup-tab-overview-alert-'+worst_status).show();
						}

						delete worst_status;
					} else {
						$('#popup-tab-overview').html('An error occured - could not connect with background task.');
					}
				});
			break;
		}
	}<commit_msg>Fix host link<commit_after>
	$(document).ready(function() {
		$('#popup-nav-overview').click(function(){ popup_nav('overview'); });
		$('#popup-nav-hosts').click(function(){ popup_nav('hosts'); });
		$('#popup-nav-services').click(function(){ popup_nav('services'); });
		$('#popup-nav-about').click(function(){ popup_nav('about'); });

		popup_nav('overview');

		$('#popup-tab-hosts-filter').on('keyup', function() { popup_nav('hosts'); });
		$('#popup-tab-services-filter').on('keyup', function() { popup_nav('services'); });
	});

	table_classes = {
		'UP': 'success',
		'DOWN': 'danger',
		'UNREACHABLE': 'info',
		'OK': 'success',
		'WARNING': 'warning',
		'UNKNOWN': 'active',
		'CRITICAL': 'danger'
	};

	function popup_nav(to) {
		$('#popup-nav li').each(function(){ $(this).removeClass('active'); });
		$('#popup-nav-'+to).parent().addClass('active');

		$('.popup-tab').each(function(){ $(this).hide(); });
		$('#popup-tab-'+to).show();

		switch(to) {
			case 'services':
				chrome.extension.sendRequest({ request: 'data' }, function(e) {
					$('#popup-tab-services-tables').empty();

					if (e.state == 'ok') {
						var instances = icinga_get_instances();

						// Go through active instances
						for(i=0; i<instances.length; i++) {
							var instance = instances[i];
							instance_line = '';

							if (instance.active) {
								// Go through all hosts and check instance
								$.each(Object.keys(e.hosts).sort(), function(h_i,h) {
									var host = e.hosts[h];
									if (host.instance == i) {
										// Host HTML Line
										switch (instance.icinga_type) {
											default: var host_name = ''+host.name+''; break;
											case 'icinga2_api': if (instance.url_web) { var host_name = ''+host.name+''; } else { var host_name = host.name; } break;
										}
										host_line = '
'+host_name+'		'+host.status+'
';
										service_line = '';

										// Go through all services
										$.each(Object.keys(host.services).sort(), function(s_i,s) {
											var service = host.services[s];

											var add_service = false;
											if ($('#popup-tab-services-filter').val()) {
												var reg = new RegExp($('#popup-tab-services-filter').val(), "i");
												if (reg.test(service.name))
													add_service = true;
											} else {
												add_service = true;
											}

											// Service HTML Line
											if (add_service) {
												switch (instance.icinga_type) {
													default: var service_name = ''+service.name+''; break;
													case 'icinga2_api': if (instance.url_web) { var service_name = ''+service.name+''; } else { var service_name = service.name; } break;
												}
												service_line += '
	'+service_name+'	'+service.status+'
';
											}
										});

										// If there is a service line OR host status down, add host line and append service lines
										if (service_line != '') {
											instance_line += host_line+service_line;
										}

										delete host_line;
										delete service_line;
									}
								});

								// Insert table
								if (instance_line) {
									$('#popup-tab-services-tables').append(''
										+ '
'
											+ '
'+instance.title+'
'
											+ '
'
												+ '
'
													+ 'Host	'
													+ 'Service	'
													+ 'Status	'
													//+ '	'
												+ '
'
											+ '
'
											+ '
'
												+ instance_line
											+ '
'
										+ '
'
									);
								}

								delete instance_line;
							}
						}
					} else {
						$('#popup-tab-hosts-tables').html('An error occured - could not connect with background task.');
					}
				});
			break;

			case 'hosts':
				chrome.extension.sendRequest({ request: 'data' }, function(e) {
					$('#popup-tab-hosts-tables').empty();

					if (e.state == 'ok') {
						var instances = icinga_get_instances();

						// Go through active instances
						for(i=0; i<instances.length; i++) {
							var instance = instances[i];
							instance_line = '';

							if (instance.active) {
								// Go through all hosts and check instance
								$.each(Object.keys(e.hosts).sort(), function(h_i,h) {
									var host = e.hosts[h];
									if (host.instance == i) {
										// regexp check filter
										var add_host = false;
										if ($('#popup-tab-hosts-filter').val()) {
											var reg = new RegExp($('#popup-tab-hosts-filter').val(), "i");
											if (reg.test(host.name))
												add_host = true;
										} else {
											add_host = true;
										}

										if (add_host) {
											// Host HTML Line
											switch (instance.icinga_type) {
												default: var host_name = ''+host.name+''; break;
												case 'icinga2_api': if (instance.url_web) { var host_name = ''+host.name+''; } else { var host_name = host.name; } break;
											}
											host_line = '
'+host_name+'	'+host.status+'
';
											instance_line += host_line;
										}

										delete host_line;
									}
								});

								// Insert table
								if (instance_line) {
									$('#popup-tab-hosts-tables').append(''
										+ '
'
											+ '
'+instance.title+'
'
											+ '
'
												+ '
'
													+ 'Host	'
													+ 'Status	'
												+ '
'
											+ '
'
											+ '
'
												+ instance_line
											+ '
'
										+ '
'
									);
								}

								delete instance_line;
							}
						}
					} else {
						$('#popup-tab-hosts-tables').html('An error occured - could not connect with background task.');
					}
				});
			break;

			case 'overview':
				chrome.extension.sendRequest({ request: 'data' }, function(e) {
					$('#popup-tab-overview-table').find('tbody').empty();
					$('#popup-tab-overview-downs').empty();
					$('#popup-tab-overview .alert').each(function(){ $(this).hide(); });

					if (e.state == 'ok') {
						var instances = icinga_get_instances();

						var worst_status = 0;

						// Go through active instances
						for(i=0; i<instances.length; i++) {
							var instance = instances[i];
							var counter_total = { hosts: 0, services: 0 };
							var counter_hosts = { up: 0, down: 0, unr: 0 };
							var counter_services = { ok: 0, warn: 0, unkn: 0, crit: 0 };
							var errors = '';

							if (instance.active && !instance.error) {
								instance_line = '';

								// Go through all hosts and check instance
								$.each(Object.keys(e.hosts), function(h_i,h) {
									var host = e.hosts[h];
									if (host.instance == i) {
										counter_total.hosts += 1;

										// Possible DOWN UNREACHABLE UP
										switch(host.status) {
											case 'UP': counter_hosts.up += 1; break;
											case 'DOWN': counter_hosts.down += 1; break;
											case 'UNREACHABLE': counter_hosts.unr += 1; break;
										}

										// Host HTML Line
										switch (instance.icinga_type) {
											default: var host_name = ''+host.name+''; break;
											case 'icinga2_api': if (instance.url_web) { var host_name = ''+host.name+''; } else { var host_name = host.name; } break;
										}
										host_line = '
'+host_name+'		'+host.status+'
';
										service_line = '';

										// Go through all services
										$.each(Object.keys(host.services), function(s_i,s) {
											var service = host.services[s];
											counter_total.services += 1;

											// Possible OK WARNING UNKNOWN CRITICAL
											switch(service.status) {
												case 'OK': counter_services.ok += 1; break;
												case 'WARNING': counter_services.warn += 1; break;
												case 'UNKNOWN': counter_services.unkn += 1; break;
												case 'CRITICAL': counter_services.crit += 1; break;
											}

											// Service HTML Line
											if (service.status == 'WARNING' || service.status == 'CRITICAL') {
												switch (instance.icinga_type) {
													default: var service_name = ''+service.name+''; break;
													case 'icinga2_api': if (instance.url_web) { var service_name = ''+service.name+''; } else { var service_name = service.name; } break;
												}
												service_line += '
	'+service_name+'	'+service.status+'
';
											}
										});

										// If there is a service line OR host status down, add host line and append service lines
										if (host.status == 'DOWN' || host.status == 'UNREACHABLE' || service_line != '') {
											instance_line += host_line+service_line;
										}

										delete host_line;
										delete service_line;
									}
								});

								// Build hosts column
								host_column = '';
								if (counter_hosts.up) host_column += ''+counter_hosts.up+' ';
								if (counter_hosts.down) host_column += ''+counter_hosts.down+' ';
								if (counter_hosts.unr) host_column += ''+counter_hosts.unr+' ';

								// Build services column
								service_column = '';
								if (counter_services.ok) service_column += ''+counter_services.ok+' ';
								if (counter_services.warn) service_column += ''+counter_services.warn+' ';
								if (counter_services.crit) service_column += ''+counter_services.crit+' ';
								if (counter_services.unkn) service_column += ''+counter_services.unkn+' ';

								// Insert into table
								$('#popup-tab-overview-table').find('tbody').append('
'
								+ ''+instance.title+'	'
								+ ''+host_column+'	'
								+ ''+service_column+'	'
								+ '
');

								// Update worst status
								if (counter_services.crit || counter_hosts.down || counter_hosts.unr) {
									var worst_status = 2;
								} else if (counter_services.warn && worst_status == 0) {
									var worst_status = 1;
								}

								// Error table
								if (instance_line) {
									$('#popup-tab-overview-downs').append(''
										+ '
'
											+ '
'+instance.title+'
'
											+ '
'
												+ '
'
													+ 'Host	'
													+ 'Service	'
													+ 'Status	'
													//+ '	'
												+ '
'
											+ '
'
											+ '
'
												+ instance_line
											+ '
'
										+ '
'
									);
								}

								delete host_column;
								delete service_column;
								delete instance_line;

							} else if (instance.active && instance.error) {
								// Insert into table
								$('#popup-tab-overview-table').find('tbody').append('
'
								+ ''+instance.title+'	'
								+ ''+instance.status_last+'	'
								+ '
');
							}

							delete counter_total;
							delete counter_hosts;
							delete counter_services;
							delete instance;
						}

						// Update alert according to worst status
						if (instances.length == 0) {
							$('#popup-tab-overview-alert-new').show();
						} else {
							$('#popup-tab-overview-alert-'+worst_status).show();
						}

						delete worst_status;
					} else {
						$('#popup-tab-overview').html('An error occured - could not connect with background task.');
					}
				});
			break;
		}
	}
<|endoftext|>


<commit_before>var clipboardData = new Array();
var clipboardURL = new Array();
var count = 0;
function saveInfo(info,tab) {

	clipboardData[count] = info.selectionText;
	clipboardURL[count++] = tab.url;
	for(i = 0; i< count; i++)
	{
		alert(clipboardData[i]);
		alert(clipboardURL[i]);
	}
}

chrome.contextMenus.create({

	title: "Add to clipboard",
	contexts:["selection"],
	onclick: saveInfo

});
<commit_msg>Image saving complete<commit_after>var clipboardData = new Array();
var clipboardURL = new Array();
var count = 0;
function saveInfo(info,tab) {

	if(info.selectionText)
	{
		clipboardData[count] = info.selectionText;
		clipboardURL[count++] = tab.url;
	}
	else if(info.srcUrl)
	{
		clipboardData[count] = info.srcUrl;
		clipboardURL[count++] = tab.url;
	}
	for(i = 0; i< count; i++)
	{
		alert(clipboardData[i]);
		alert(clipboardURL[i]);
	}
}

chrome.contextMenus.create({

	title: "Add to clipboard",
	contexts:["all"],
	onclick: saveInfo

});
<|endoftext|>


<commit_before>'use strict';
var fs = require('fs');

var angular = require('camunda-bpm-sdk-js/vendor/angular'),
    Viewer = require('bpmn-js/lib/NavigatedViewer'),

    template = fs.readFileSync(__dirname + '/cam-widget-bpmn-viewer.html', 'utf8');

  module.exports = ['$compile', '$location', '$rootScope', 'search',
  function($compile,   $location,   $rootScope,   search) {

    return {
      scope: {
        diagramData: '=',
        control: '=?',
        disableNavigation: '&',
        onLoad: '&',
        onClick: '&',
        onMouseEnter: '&',
        onMouseLeave: '&'
      },

      template: template,

      link: function($scope, $element) {

        var definitions;

        $scope.grabbing = false;

        // parse boolean
        $scope.disableNavigation = $scope.$eval($scope.disableNavigation);

        // --- CONTROL FUNCTIONS ---
        $scope.control = $scope.control || {};

        $scope.control.highlight = function(id) {
          canvas.addMarker(id, 'highlight');

          $element.find('[data-element-id="'+id+'"]>.djs-outline').attr({
            rx: '14px',
            ry: '14px'
          });
        };

        $scope.control.clearHighlight = function(id) {
          canvas.removeMarker(id, 'highlight');
        };

        $scope.control.isHighlighted = function(id) {
          return canvas.hasMarker(id, 'highlight');
        };

        // config: text, tooltip, color, position
        $scope.control.createBadge = function(id, config) {
          var overlays = viewer.get('overlays');

          var htmlElement;
          if(config.html) {
            htmlElement = config.html;
          } else {
            htmlElement = document.createElement('span');
            if(config.color) {
              htmlElement.style['background-color'] = config.color;
            }
            if(config.tooltip) {
              htmlElement.setAttribute('tooltip', config.tooltip);
              htmlElement.setAttribute('tooltip-placement', 'top');
            }
            if(config.text) {
              htmlElement.appendChild(document.createTextNode(config.text));
            }
          }

          var overlayId = overlays.add(id, {
            position: config.position || {
              bottom: 0,
              right: 0
            },
            show: {
              minZoom: -Infinity,
              maxZoom: +Infinity
            },
            html: htmlElement
          });

          $compile(htmlElement)($scope);

          return overlayId;
        };

        // removes all badges for an element with a given id
        $scope.control.removeBadges = function(id) {
          viewer.get('overlays').remove({element:id});
        };

        // removes a single badge with a given id
        $scope.control.removeBadge = function(id) {
          viewer.get('overlays').remove(id);
        };

        $scope.control.getViewer = function() {
          return viewer;
        };

        $scope.control.scrollToElement = function(element) {
          var height, width, x, y;

          var elem = viewer.get('elementRegistry').get(element);
          var viewbox = canvas.viewbox();

          height = Math.max(viewbox.height, elem.height);
          width  = Math.max(viewbox.width,  elem.width);

          x = Math.min(Math.max(viewbox.x, elem.x - viewbox.width + elem.width), elem.x);
          y = Math.min(Math.max(viewbox.y, elem.y - viewbox.height + elem.height), elem.y);

          canvas.viewbox({
            x: x,
            y: y,
            width: width,
            height: height
          });
        };

        $scope.control.getElement = function(elementId) {
          return viewer.get('elementRegistry').get(elementId);
        };

        $scope.control.getElements = function(filter) {
          return viewer.get('elementRegistry').filter(filter);
        };

        $scope.loaded = false;
        $scope.control.isLoaded = function() {
          return $scope.loaded;
        };

        $scope.control.addAction = function(config) {
          var container = $element.find('.actions');
          var htmlElement = config.html;
          container.append(htmlElement);
          $compile(htmlElement)($scope);
        };

        $scope.control.addImage = function(image, x, y) {
          var addedImage = canvas._viewport.image(image, x, y);
          return addedImage;
        };

        var BpmnViewer = Viewer;
        if($scope.disableNavigation) {
          BpmnViewer = Object.getPrototypeOf(Viewer.prototype).constructor;
        }
        var viewer = new BpmnViewer({
          container: $element[0].querySelector('.diagram-holder'),
          width: '100%',
          height: '100%',
          canvas: {
            deferUpdate: false
          }
        });

        var diagramData = null;
        var canvas = null;

        $scope.$watch('diagramData', function(newValue) {
          if (newValue) {
            diagramData = newValue;
            renderDiagram();
          }
        });

        function renderDiagram() {
          if (diagramData) {

            $scope.loaded = false;

            var useDefinitions = (typeof diagramData === 'object');

            var importFunction = (useDefinitions ? viewer.importDefinitions : viewer.importXML).bind(viewer);

            importFunction(diagramData, function(err, warn) {

              var applyFunction = useDefinitions ? function(fn){fn();} : $scope.$apply.bind($scope);

              applyFunction(function() {
                if (err) {
                  $scope.error = err;
                  return;
                }
                $scope.warn = warn;
                canvas = viewer.get('canvas');
                definitions = viewer.definitions;
                zoom();
                setupEventListeners();
                $scope.loaded = true;
                $scope.onLoad();
              });
            });
          }
        }

        function zoom() {
          if (canvas) {
            var viewbox = JSON.parse(($location.search() || {}).viewbox || '{}')[definitions.id];

            if (viewbox) {
              canvas.viewbox(viewbox);
            }
            else {
              canvas.zoom('fit-viewport', 'auto');
            }
          }
        }

        var mouseReleaseCallback = function() {
          $scope.grabbing = false;
          document.removeEventListener('mouseup', mouseReleaseCallback);
          $scope.$apply();
        };

        function setupEventListeners() {
          var eventBus = viewer.get('eventBus');
          eventBus.on('element.click', function(e) {
            // e.element = the model element
            // e.gfx = the graphical element
            $scope.onClick({element: e.element, $event: e.originalEvent});
          });
          eventBus.on('element.hover', function(e) {
            $scope.onMouseEnter({element: e.element, $event: e.originalEvent});
          });
          eventBus.on('element.out', function(e) {
            $scope.onMouseLeave({element: e.element, $event: e.originalEvent});
          });
          eventBus.on('element.mousedown', function() {
            $scope.grabbing = true;

            document.addEventListener('mouseup', mouseReleaseCallback);

            $scope.$apply();
          });
          eventBus.on('canvas.viewbox.changed', function(e) {
            var viewbox = JSON.parse(($location.search() || {}).viewbox || '{}');

            viewbox[definitions.id] = {
              x: e.viewbox.x,
              y: e.viewbox.y,
              width: e.viewbox.width,
              height: e.viewbox.height
            };

            search.updateSilently({
              viewbox: JSON.stringify(viewbox)
            });

            var phase = $rootScope.$$phase;
            if (phase !== '$apply' && phase !== '$digest') {
              $scope.$apply(function () {
                $location.replace();
              });
            } else {
              $location.replace();
            }
          });
        }

        $scope.zoomIn = function() {
          viewer.get('zoomScroll').zoom(1, {
            x: $element[0].offsetWidth / 2,
            y: $element[0].offsetHeight / 2
          });
        };

        $scope.zoomOut = function() {
          viewer.get('zoomScroll').zoom(-1, {
            x: $element[0].offsetWidth / 2,
            y: $element[0].offsetHeight / 2
          });
        };

        $scope.resetZoom = function() {
          canvas.zoom('fit-viewport', 'auto');
        };
        $scope.control.resetZoom = $scope.resetZoom;

      }
    };
  }];
<commit_msg>impr(bpmn-viewer): improve canvas move operation<commit_after>'use strict';
var fs = require('fs');

var angular = require('camunda-bpm-sdk-js/vendor/angular'),
    Viewer = require('bpmn-js/lib/NavigatedViewer'),

    template = fs.readFileSync(__dirname + '/cam-widget-bpmn-viewer.html', 'utf8');

  module.exports = ['$compile', '$location', '$rootScope', 'search', 'debounce',
  function($compile,   $location,   $rootScope,   search, debounce) {

    return {
      scope: {
        diagramData: '=',
        control: '=?',
        disableNavigation: '&',
        onLoad: '&',
        onClick: '&',
        onMouseEnter: '&',
        onMouseLeave: '&'
      },

      template: template,

      link: function($scope, $element) {

        var definitions;

        $scope.grabbing = false;

        // parse boolean
        $scope.disableNavigation = $scope.$eval($scope.disableNavigation);

        // --- CONTROL FUNCTIONS ---
        $scope.control = $scope.control || {};

        $scope.control.highlight = function(id) {
          canvas.addMarker(id, 'highlight');

          $element.find('[data-element-id="'+id+'"]>.djs-outline').attr({
            rx: '14px',
            ry: '14px'
          });
        };

        $scope.control.clearHighlight = function(id) {
          canvas.removeMarker(id, 'highlight');
        };

        $scope.control.isHighlighted = function(id) {
          return canvas.hasMarker(id, 'highlight');
        };

        // config: text, tooltip, color, position
        $scope.control.createBadge = function(id, config) {
          var overlays = viewer.get('overlays');

          var htmlElement;
          if(config.html) {
            htmlElement = config.html;
          } else {
            htmlElement = document.createElement('span');
            if(config.color) {
              htmlElement.style['background-color'] = config.color;
            }
            if(config.tooltip) {
              htmlElement.setAttribute('tooltip', config.tooltip);
              htmlElement.setAttribute('tooltip-placement', 'top');
            }
            if(config.text) {
              htmlElement.appendChild(document.createTextNode(config.text));
            }
          }

          var overlayId = overlays.add(id, {
            position: config.position || {
              bottom: 0,
              right: 0
            },
            show: {
              minZoom: -Infinity,
              maxZoom: +Infinity
            },
            html: htmlElement
          });

          $compile(htmlElement)($scope);

          return overlayId;
        };

        // removes all badges for an element with a given id
        $scope.control.removeBadges = function(id) {
          viewer.get('overlays').remove({element:id});
        };

        // removes a single badge with a given id
        $scope.control.removeBadge = function(id) {
          viewer.get('overlays').remove(id);
        };

        $scope.control.getViewer = function() {
          return viewer;
        };

        $scope.control.scrollToElement = function(element) {
          var height, width, x, y;

          var elem = viewer.get('elementRegistry').get(element);
          var viewbox = canvas.viewbox();

          height = Math.max(viewbox.height, elem.height);
          width  = Math.max(viewbox.width,  elem.width);

          x = Math.min(Math.max(viewbox.x, elem.x - viewbox.width + elem.width), elem.x);
          y = Math.min(Math.max(viewbox.y, elem.y - viewbox.height + elem.height), elem.y);

          canvas.viewbox({
            x: x,
            y: y,
            width: width,
            height: height
          });
        };

        $scope.control.getElement = function(elementId) {
          return viewer.get('elementRegistry').get(elementId);
        };

        $scope.control.getElements = function(filter) {
          return viewer.get('elementRegistry').filter(filter);
        };

        $scope.loaded = false;
        $scope.control.isLoaded = function() {
          return $scope.loaded;
        };

        $scope.control.addAction = function(config) {
          var container = $element.find('.actions');
          var htmlElement = config.html;
          container.append(htmlElement);
          $compile(htmlElement)($scope);
        };

        $scope.control.addImage = function(image, x, y) {
          var addedImage = canvas._viewport.image(image, x, y);
          return addedImage;
        };

        var BpmnViewer = Viewer;
        if($scope.disableNavigation) {
          BpmnViewer = Object.getPrototypeOf(Viewer.prototype).constructor;
        }
        var viewer = new BpmnViewer({
          container: $element[0].querySelector('.diagram-holder'),
          width: '100%',
          height: '100%',
          canvas: {
            deferUpdate: false
          }
        });

        // The following logic mirrors diagram-js to defer its update of the viewbox change.
        // We tell diagram-js to not defer the update (see above) and do it ourselves instead.
        // Only difference: We use a delay of 0. This causes the update to basically be propagated
        // immediately after the current execution is finished (instead of halting the execution
        // until the viewbox changes and all event listeners are executed). This results in a much
        // better performance while moving the diagram, but at a cost: In the interval between the
        // trigger of the viewbox change and the calculation of the event handlers in the debounced
        // execution, things like badges or migration arrows are at the wrong position; they feel
        // like they are "dragged behind". Therefore, we temporarily hide the overlays.

        // patch show and hide of overlays
        var originalShow = viewer.get('overlays').show.bind(viewer.get('overlays'));
        viewer.get('overlays').show = function() {
          viewer.get('eventBus').fire('overlays.show');
          originalShow();
        }

        var originalHide = viewer.get('overlays').hide.bind(viewer.get('overlays'));
        viewer.get('overlays').hide = function() {
          viewer.get('eventBus').fire('overlays.hide');
          originalHide();
        }

        var showAgain = debounce(function() {
          viewer.get('overlays').show();
        }, 300);

        var originalViewboxChanged = viewer.get('canvas')._viewboxChanged.bind(viewer.get('canvas'));
        var debouncedOriginal = debounce(function() {
          originalViewboxChanged();
          viewer.get('overlays').hide();
          showAgain();
        }, 0);
        viewer.get('canvas')._viewboxChanged = function() {
          debouncedOriginal();
        }

        var diagramData = null;
        var canvas = null;

        $scope.$watch('diagramData', function(newValue) {
          if (newValue) {
            diagramData = newValue;
            renderDiagram();
          }
        });

        function renderDiagram() {
          if (diagramData) {

            $scope.loaded = false;

            var useDefinitions = (typeof diagramData === 'object');

            var importFunction = (useDefinitions ? viewer.importDefinitions : viewer.importXML).bind(viewer);

            importFunction(diagramData, function(err, warn) {

              var applyFunction = useDefinitions ? function(fn){fn();} : $scope.$apply.bind($scope);

              applyFunction(function() {
                if (err) {
                  $scope.error = err;
                  return;
                }
                $scope.warn = warn;
                canvas = viewer.get('canvas');
                definitions = viewer.definitions;
                zoom();
                setupEventListeners();
                $scope.loaded = true;
                $scope.onLoad();
              });
            });
          }
        }

        function zoom() {
          if (canvas) {
            var viewbox = JSON.parse(($location.search() || {}).viewbox || '{}')[definitions.id];

            if (viewbox) {
              canvas.viewbox(viewbox);
            }
            else {
              canvas.zoom('fit-viewport', 'auto');
            }
          }
        }

        var mouseReleaseCallback = function() {
          $scope.grabbing = false;
          document.removeEventListener('mouseup', mouseReleaseCallback);
          $scope.$apply();
        };

        function setupEventListeners() {
          var eventBus = viewer.get('eventBus');
          eventBus.on('element.click', function(e) {
            // e.element = the model element
            // e.gfx = the graphical element
            $scope.onClick({element: e.element, $event: e.originalEvent});
          });
          eventBus.on('element.hover', function(e) {
            $scope.onMouseEnter({element: e.element, $event: e.originalEvent});
          });
          eventBus.on('element.out', function(e) {
            $scope.onMouseLeave({element: e.element, $event: e.originalEvent});
          });
          eventBus.on('element.mousedown', function() {
            $scope.grabbing = true;

            document.addEventListener('mouseup', mouseReleaseCallback);

            $scope.$apply();
          });
          eventBus.on('canvas.viewbox.changed', debounce(function(e) {
            var viewbox = JSON.parse(($location.search() || {}).viewbox || '{}');

            viewbox[definitions.id] = {
              x: e.viewbox.x,
              y: e.viewbox.y,
              width: e.viewbox.width,
              height: e.viewbox.height
            };

            search.updateSilently({
              viewbox: JSON.stringify(viewbox)
            });

            var phase = $rootScope.$$phase;
            if (phase !== '$apply' && phase !== '$digest') {
              $scope.$apply(function () {
                $location.replace();
              });
            } else {
              $location.replace();
            }
          }, 500));
        }

        $scope.zoomIn = function() {
          viewer.get('zoomScroll').zoom(1, {
            x: $element[0].offsetWidth / 2,
            y: $element[0].offsetHeight / 2
          });
        };

        $scope.zoomOut = function() {
          viewer.get('zoomScroll').zoom(-1, {
            x: $element[0].offsetWidth / 2,
            y: $element[0].offsetHeight / 2
          });
        };

        $scope.resetZoom = function() {
          canvas.zoom('fit-viewport', 'auto');
        };
        $scope.control.resetZoom = $scope.resetZoom;

      }
    };
  }];
<|endoftext|>


<commit_before>var express = require('express'),
  router = express.Router(),
  mongoose = require('mongoose'),
  request = require('request');

var path = require('path');
var firstBy = require('thenby');

var _ = require('lodash');

// pega os models
var Aluno = require("../models/aluno");
var Disciplina = require("../models/disciplina");

module.exports = function (app) {
  app.use('/', router);
};

last_date = new Date();

var cursos_ids = {
  'Bacharelado em Ciências da Computação' : 16,
  'Bacharelado em Ciência da Computação': 16,
  'Bacharelado em Ciência e Tecnologia': 20,
  'Bacharelado em Ciências Biológicas': 17,
  'Bacharelado em Ciências Econômicas': 1,
  'Bacharelado em Ciências e Humanidades': 22,
  'Bacharelado em Filosofia': 10,
  'Bacharelado em Física': 28,
  'Bacharelado em Matemática': 21,
  'Bacharelado em Neurociência' : 24,
  'Bacharelado em Planejamento Territorial': 11,
  'Bacharelado em Políticas Públicas': 3,
  'Bacharelado em Química': 14,
  'Bacharelado em Relações Internacionais': 27,
  'Engenharia Aeroespacial': 26,
  'Engenharia Ambiental e Urbana': 6,
  'Engenharia Biomédica': 18,
  'Engenharia de Energia': 7,
  'Engenharia de Gestão': 23,
  'Engenharia de Informação' : 8,
  'Engenharia de Instrumentação, Automação e Robótica': 2,
  'Engenharia de Materiais': 15,
  'Licenciatura em Ciências Biológicas': 13,
  'Licenciatura em Física': 25,
  'Licenciatura em Matemática': 9,
  'Licenciatura em Química': 4
}

router.get('/disciplinas', function (req, res, next) {
  res.charset = 'ISO-8859-1';
  res.header('Last-Modified', last_date);
  res.sendFile(path.join(__dirname, '../../build/tmp', 'processed.json'));
});

router.get('/horarios', function (req, res, next) {
  res.charset = 'ISO-8859-1';
  res.header('Last-Modified', last_date);
  res.sendFile(path.join(__dirname, '../../build/tmp', 'horarios.json'));
});

//deve fazer update, nao apenas criar
router.post('/test', function (req, res, next) {
  var cursos = req.body.data;
  var aluno_id = req.body.aluno_id;
  var cursos_salvar = [];
  for (var i = 0; i < cursos.length; i++) {
    var curso_obj = {};
    curso_obj['cp'] = parseFloat(cursos[i].cp.replace(',','.'));
    curso_obj['cr'] = parseFloat(cursos[i].cr.replace(',','.'));
    curso_obj['nome_curso'] = cursos[i].curso;
    curso_obj['turno'] = cursos[i].turno;
    curso_obj['ind_afinidade'] = 0.07 * curso_obj['cr'] + 0.63 * curso_obj['cp'];
    curso_obj['id_curso'] = cursos_ids[curso_obj['nome_curso']];
    cursos_salvar.push(curso_obj);
  }
  Aluno.create({aluno_id: aluno_id, cursos: cursos_salvar}, function (err, aluno) {
    if (err) {
      res.send(err);
    } else {
      res.send(aluno);
    }

  })
});

var discover_obg = {
  'bct' : [22,24,14,16,3,17,4,27,25,20,13,28]
}

// simula uma disciplina
router.post('/simula', function (req, res, next) {
  var disciplina_id = parseInt(req.body.disciplina_id);
  var aluno_id = parseInt(req.body.aluno_id);
  // recebe um aluno_id e disciplina_id
  Disciplina.aggregate([{
    $match: {disciplina_id : disciplina_id}
  }, {
    $unwind : "$alunos_matriculados"
  },{
    $unwind : "$alunos_matriculados.cursos"
  }, {
    $project: {
      turno: 1,
      ideal_quad: 1,
      aluno_id: "$alunos_matriculados.aluno_id",
      aluno : "$alunos_matriculados.cursos"
    }
  }], function (err, resp) {
    // se nao conseguir pegar o turno
    // eh pq nao tem conhecimento de nenhum cidado na turma
    try {
        var turno_disciplina = resp[0].turno;
        var ideal = resp[0].ideal_quad;
    } catch (err) {
      res.json({pos: 1, total: 1});
      return;
    }
    // escolhe como vai filtrar por turno
    var sort_turno = 0;
    if (turno_disciplina == "diurno") {
      sort_turno = 1;
    } else if (turno_disciplina == "noturno") {
      sort_turno = -1;
    }
    // aqui "faz o corte"
    // 1 -> prioridade Diurno
    // -1 -> prioridade Noturno
    //
    // alem disso precisa escolher se vai fazer por cr ou por cp
    // se for quad ideal faz por cr
    // senao faz por CP
    if (ideal) {
      resp.sort(
        firstBy('aluno.turno', sort_turno)
        .thenBy(function (v1,v2) {return v1.aluno.cr < v2.aluno.cr;})
      );
    } else {
      resp.sort(
        firstBy('aluno.turno', sort_turno)
        .thenBy(function (v1,v2) {return v1.aluno.cp < v2.aluno.cp;})
      );
    }
    var sem_duplicados = _.uniqBy(resp, 'aluno_id');
    var pos = _.findIndex(resp, { 'aluno_id': aluno_id });
    res.json({pos: pos + 1 , total: sem_duplicados.length});
    }
  )
})

// function (v1,v2) {return v1.aluno.cp < v2.aluno.cp};

// importa todas as disciplinas ofertadas em determinado quadrimestre
// roda apenas uma vez no quadrimestre
router.get('/import_disciplinas', function (req, res, next) {
  // isso eh feito apenas uma vez por quad
  // pega a lista de disciplinas com suas disciplias obrigatorias
  request('https://matricula.ufabc.edu.br/cache/todasDisciplinas.js', function (error, response, body) {
    if (!error && response.statusCode == 200) {
      data = JSON.parse(body.replace('todasDisciplinas=', '').replace(';', ''));
      var save = [];
      // cria todas os objetos de disciplinas
      for (var j = 0; j < data.length; j++) {
        var obrigatorias = data[j].obrigatoriedades;
        var obg = [];
        // pega os cursos_id que tem essa disciplinas como obrigatoria
        for (var i = 0; i < obrigatorias.length; i++) {
          obg.push(obrigatorias[i].curso_id);
        }
        // cria obj no braço
        var obj = {};
        obj['disciplina_id'] = data[j].id;
        obj['vagas'] = data[j].vagas;
        obj['codigo'] = data[j].codigo;
        obj['obrigatorias'] = obg;
        obj['ideal_quad'] = false;
        obj['alunos_matriculados'] = [];
        if (data[j].nome.indexOf("Noturno") != -1) {
          obj['turno'] = "noturno";
        } else if (data[j].nome.indexOf("Matutino") != -1) {
          obj['turno'] = "diurno";
        }
        // push para o vetor que ira ser enviado para o DB
        save.push(obj);
      }
      // salva no banco de dados
      Disciplina.create(save, function (err, resp) {
        if (err) {
          res.send("Erro :" + err);
        } else {
          res.send("Parece que deu certo");
        }
      });
    }
  })
})

// essa funcao tem que ser rodada a cada sei la, 30 segundos

setInterval(function () {recalculaDisciplinas();}, 60000);

function recalculaDisciplinas () {
  request('https://matricula.ufabc.edu.br/cache/matriculas.js', function (error, response, body) {
    try {
      data = JSON.parse(body.replace('matriculas=', '').replace(';', ''));
    } catch (err) {
      console.log("N calculando...");
      return;
    }
    console.log("Calculando...");
    var matriculas = {};
    // cria um vetor para ser usado no mongo dos alunos
    var in_aluno = [];

    // data sao as disciplinas que ele se matriculou
    for (var aluno_id in data) {
      in_aluno.push(aluno_id);
      for (var i = 0; i < data[aluno_id].length; i++) {
        // data[key][i] é o id_disciplina que o aluno_id (key pegou)
        try {
          matriculas[data[aluno_id][i]] = matriculas[data[aluno_id][i]].concat([parseInt(aluno_id)]);
        } catch (err) {
          matriculas[data[aluno_id][i]] = [parseInt(aluno_id)];
        }
      }
    }
    // cria um vetor para ser usado no Mongo das matriculas
    var in_mat = [];
    for (key in matriculas) {
      in_mat.push(key);
    }
    // precisa dar um update das disciplinas com a info dos alunos
    Disciplina.find({disciplina_id: {'$in': in_mat}}).exec(function (err, disciplinas) {
      Aluno.find({aluno_id : {'$in': in_aluno}}).lean().exec(function (err, users) {
        // transforma users para uma hash
        var hash_users = {};
        for (var i = 0; i < users.length; i++) {
          hash_users[parseInt(users[i].aluno_id)] = users[i];
        }
        // itera sobre todas as disciplinas e atualiza suas matriculas
        for (var i = 0; i < disciplinas.length; i++) {
          var mat_disciplinas = (matriculas[disciplinas[i].disciplina_id]);
          var updated_disc = [];
          disciplinas[i].alunos_matriculados = [];
          for (var j = 0; j < mat_disciplinas.length; j++) {
            if (hash_users[mat_disciplinas[j]] != null) {
              disciplinas[i].alunos_matriculados.push(hash_users[mat_disciplinas[j]]);
            };
          }
          disciplinas[i].save();
        }
      })
    });

  })

};

// check if an element exists in array using a comparer function
// comparer : function(currentElement)
Array.prototype.inArray = function(comparer) {
    for(var i=0; i < this.length; i++) {
        if(comparer(this[i])) return true;
    }
    return false;
};

// adds an element to the array if it does not already exist using a comparer
// function
Array.prototype.pushIfNotExist = function(element, comparer) {
    if (!this.inArray(comparer)) {
        this.push(element);
    }
};

// NI, GA, FUV, FEMEC, BIODIVERSIDADE -> 2 QUAD
// QUANTICA, BIOQUIMICA, EDS

var disciplinas_ideal = [
  'BCM0504-15',
  'BCN0404-15',
  'BCN0402-15',
  'BCJ0204-15',
  'BCL0306-15',
  'BCK0103-15',
  'BCL0308-15',
  'BIQ0602-15'
]

// atualiza as disciplinas para o quad ideal

router.get('/update_ideal', function (req, res, next) {
  // para cada discipina ideal faca
  for (var j = 0; j < disciplinas_ideal.length; j++) {
      Disciplina.find({codigo : disciplinas_ideal[j]}).exec(function (err, resp) {
        for (var i = 0; i < resp.length; i++) {
          resp[i].ideal_quad = true;
          resp[i].save();
        }
      })
  }
  res.json('OK');
});<commit_msg>Fix na ordenacao do turno<commit_after>var express = require('express'),
  router = express.Router(),
  mongoose = require('mongoose'),
  request = require('request');

var path = require('path');
var firstBy = require('thenby');

var _ = require('lodash');

// pega os models
var Aluno = require("../models/aluno");
var Disciplina = require("../models/disciplina");

module.exports = function (app) {
  app.use('/', router);
};

last_date = new Date();

var cursos_ids = {
  'Bacharelado em Ciências da Computação' : 16,
  'Bacharelado em Ciência da Computação': 16,
  'Bacharelado em Ciência e Tecnologia': 20,
  'Bacharelado em Ciências Biológicas': 17,
  'Bacharelado em Ciências Econômicas': 1,
  'Bacharelado em Ciências e Humanidades': 22,
  'Bacharelado em Filosofia': 10,
  'Bacharelado em Física': 28,
  'Bacharelado em Matemática': 21,
  'Bacharelado em Neurociência' : 24,
  'Bacharelado em Planejamento Territorial': 11,
  'Bacharelado em Políticas Públicas': 3,
  'Bacharelado em Química': 14,
  'Bacharelado em Relações Internacionais': 27,
  'Engenharia Aeroespacial': 26,
  'Engenharia Ambiental e Urbana': 6,
  'Engenharia Biomédica': 18,
  'Engenharia de Energia': 7,
  'Engenharia de Gestão': 23,
  'Engenharia de Informação' : 8,
  'Engenharia de Instrumentação, Automação e Robótica': 2,
  'Engenharia de Materiais': 15,
  'Licenciatura em Ciências Biológicas': 13,
  'Licenciatura em Física': 25,
  'Licenciatura em Matemática': 9,
  'Licenciatura em Química': 4
}

router.get('/disciplinas', function (req, res, next) {
  res.charset = 'ISO-8859-1';
  res.header('Last-Modified', last_date);
  res.sendFile(path.join(__dirname, '../../build/tmp', 'processed.json'));
});

router.get('/horarios', function (req, res, next) {
  res.charset = 'ISO-8859-1';
  res.header('Last-Modified', last_date);
  res.sendFile(path.join(__dirname, '../../build/tmp', 'horarios.json'));
});

//deve fazer update, nao apenas criar
router.post('/test', function (req, res, next) {
  var cursos = req.body.data;
  var aluno_id = req.body.aluno_id;
  var cursos_salvar = [];
  for (var i = 0; i < cursos.length; i++) {
    var curso_obj = {};
    curso_obj['cp'] = parseFloat(cursos[i].cp.replace(',','.'));
    curso_obj['cr'] = parseFloat(cursos[i].cr.replace(',','.'));
    curso_obj['nome_curso'] = cursos[i].curso;
    curso_obj['turno'] = cursos[i].turno;
    curso_obj['ind_afinidade'] = 0.07 * curso_obj['cr'] + 0.63 * curso_obj['cp'];
    curso_obj['id_curso'] = cursos_ids[curso_obj['nome_curso']];
    cursos_salvar.push(curso_obj);
  }
  Aluno.create({aluno_id: aluno_id, cursos: cursos_salvar}, function (err, aluno) {
    if (err) {
      res.send(err);
    } else {
      res.send(aluno);
    }

  })
});

var discover_obg = {
  'bct' : [22,24,14,16,3,17,4,27,25,20,13,28]
}

// simula uma disciplina
router.post('/simula_old', function (req, res, next) {
  var disciplina_id = parseInt(req.body.disciplina_id);
  var aluno_id = parseInt(req.body.aluno_id);
  // recebe um aluno_id e disciplina_id
  Disciplina.aggregate([{
    $match: {disciplina_id : disciplina_id}
  }, {
    $unwind : "$alunos_matriculados"
  },{
    $unwind : "$alunos_matriculados.cursos"
  }, {
    $project: {
      turno: 1,
      ideal_quad: 1,
      aluno_id: "$alunos_matriculados.aluno_id",
      aluno : "$alunos_matriculados.cursos"
    }
  }], function (err, resp) {
    // se nao conseguir pegar o turno
    // eh pq nao tem conhecimento de nenhum cidado na turma
    try {
        var turno_disciplina = resp[0].turno;
        var ideal = resp[0].ideal_quad;
    } catch (err) {
      res.json({pos: 1, total: 1});
      return;
    }
    // escolhe como vai filtrar por turno
    var sort_turno = 0;
    if (turno_disciplina == "diurno") {
      sort_turno = 1;
    } else if (turno_disciplina == "noturno") {
      sort_turno = -1;
    }
    // aqui "faz o corte"
    // 1 -> prioridade Diurno
    // -1 -> prioridade Noturno
    //
    // alem disso precisa escolher se vai fazer por cr ou por cp
    // se for quad ideal faz por cr
    // senao faz por CP
    if (ideal) {
      resp.sort(
        firstBy('aluno.turno', sort_turno)
        .thenBy(function (v1,v2) {return v1.aluno.cr < v2.aluno.cr;})
      );
    } else {
      resp.sort(
        firstBy('aluno.turno', sort_turno)
        .thenBy(function (v1,v2) {return v1.aluno.cp < v2.aluno.cp;})
      );
    }
    var sem_duplicados = _.uniqBy(resp, 'aluno_id');
    var pos = _.findIndex(resp, { 'aluno_id': aluno_id });
    res.json({pos: pos + 1 , total: sem_duplicados.length});
    }
  )
})

router.post('/simula', function (req, res, next) {
  var disciplina_id = parseInt(req.body.disciplina_id);
  var aluno_id = parseInt(req.body.aluno_id);
  // recebe um aluno_id e disciplina_id
  Disciplina.aggregate([{
    $match: {disciplina_id : disciplina_id}
  }, {
    $unwind : "$alunos_matriculados"
  },{
    $unwind : "$alunos_matriculados.cursos"
  }, {
    $project: {
      turno: 1,
      ideal_quad: 1,
      aluno_id: "$alunos_matriculados.aluno_id",
      aluno : "$alunos_matriculados.cursos"
    }
  }], function (err, resp) {
    // se nao conseguir pegar o turno
    // eh pq nao tem conhecimento de nenhum cidado na turma
    try {
        var turno_disciplina = resp[0].turno;
        var ideal = resp[0].ideal_quad;
    } catch (err) {
      res.json({pos: 1, total: 1});
      return;
    }
    // escolhe como vai filtrar por turno
    var sort_turno = 0;
    if (turno_disciplina == "diurno") {
      sort_turno = 'asc';
    } else if (turno_disciplina == "noturno") {
      sort_turno = 'desc';
    }

    // aqui "faz o corte"
    // 1 -> prioridade Diurno
    // -1 -> prioridade Noturno
    //
    // alem disso precisa escolher se vai fazer por cr ou por cp
    // se for quad ideal faz por cr
    // senao faz por CP
    var sort_type = ""
    if (ideal) {
      sort_type = 'aluno.cr';
    } else {
      sort_type = 'aluno.cp';
    }

    var test = _.orderBy(resp, ['aluno.turno', sort_type], [sort_turno, 'desc']);
    var sem_duplicados = _.uniqBy(test, 'aluno_id');
    var pos = _.findIndex(sem_duplicados, { 'aluno_id': aluno_id });
    res.json({pos: pos + 1 , total: sem_duplicados.length});
    }
  )
})

// function (v1,v2) {return v1.aluno.cp < v2.aluno.cp};

// importa todas as disciplinas ofertadas em determinado quadrimestre
// roda apenas uma vez no quadrimestre
router.get('/import_disciplinas', function (req, res, next) {
  // isso eh feito apenas uma vez por quad
  // pega a lista de disciplinas com suas disciplias obrigatorias
  request('https://matricula.ufabc.edu.br/cache/todasDisciplinas.js', function (error, response, body) {
    if (!error && response.statusCode == 200) {
      data = JSON.parse(body.replace('todasDisciplinas=', '').replace(';', ''));
      var save = [];
      // cria todas os objetos de disciplinas
      for (var j = 0; j < data.length; j++) {
        var obrigatorias = data[j].obrigatoriedades;
        var obg = [];
        // pega os cursos_id que tem essa disciplinas como obrigatoria
        for (var i = 0; i < obrigatorias.length; i++) {
          obg.push(obrigatorias[i].curso_id);
        }
        // cria obj no braço
        var obj = {};
        obj['disciplina_id'] = data[j].id;
        obj['vagas'] = data[j].vagas;
        obj['codigo'] = data[j].codigo;
        obj['obrigatorias'] = obg;
        obj['ideal_quad'] = false;
        obj['alunos_matriculados'] = [];
        if (data[j].nome.indexOf("Noturno") != -1) {
          obj['turno'] = "noturno";
        } else if (data[j].nome.indexOf("Matutino") != -1) {
          obj['turno'] = "diurno";
        }
        // push para o vetor que ira ser enviado para o DB
        save.push(obj);
      }
      // salva no banco de dados
      Disciplina.create(save, function (err, resp) {
        if (err) {
          res.send("Erro :" + err);
        } else {
          res.send("Parece que deu certo");
        }
      });
    }
  })
})

// essa funcao tem que ser rodada a cada sei la, 30 segundos

setInterval(function () {recalculaDisciplinas();}, 60000);

function recalculaDisciplinas () {
  request('https://matricula.ufabc.edu.br/cache/matriculas.js', function (error, response, body) {
    try {
      data = JSON.parse(body.replace('matriculas=', '').replace(';', ''));
    } catch (err) {
      console.log("N calculando...");
      return;
    }
    console.log("Calculando...");
    var matriculas = {};
    // cria um vetor para ser usado no mongo dos alunos
    var in_aluno = [];

    // data sao as disciplinas que ele se matriculou
    for (var aluno_id in data) {
      in_aluno.push(aluno_id);
      for (var i = 0; i < data[aluno_id].length; i++) {
        // data[key][i] é o id_disciplina que o aluno_id (key pegou)
        try {
          matriculas[data[aluno_id][i]] = matriculas[data[aluno_id][i]].concat([parseInt(aluno_id)]);
        } catch (err) {
          matriculas[data[aluno_id][i]] = [parseInt(aluno_id)];
        }
      }
    }
    // cria um vetor para ser usado no Mongo das matriculas
    var in_mat = [];
    for (key in matriculas) {
      in_mat.push(key);
    }
    // precisa dar um update das disciplinas com a info dos alunos
    Disciplina.find({disciplina_id: {'$in': in_mat}}).exec(function (err, disciplinas) {
      Aluno.find({aluno_id : {'$in': in_aluno}}).lean().exec(function (err, users) {
        // transforma users para uma hash
        var hash_users = {};
        for (var i = 0; i < users.length; i++) {
          hash_users[parseInt(users[i].aluno_id)] = users[i];
        }
        // itera sobre todas as disciplinas e atualiza suas matriculas
        for (var i = 0; i < disciplinas.length; i++) {
          var mat_disciplinas = (matriculas[disciplinas[i].disciplina_id]);
          var updated_disc = [];
          disciplinas[i].alunos_matriculados = [];
          for (var j = 0; j < mat_disciplinas.length; j++) {
            if (hash_users[mat_disciplinas[j]] != null) {
              disciplinas[i].alunos_matriculados.push(hash_users[mat_disciplinas[j]]);
            };
          }
          disciplinas[i].save();
        }
      })
    });

  })

};

// check if an element exists in array using a comparer function
// comparer : function(currentElement)
Array.prototype.inArray = function(comparer) {
    for(var i=0; i < this.length; i++) {
        if(comparer(this[i])) return true;
    }
    return false;
};

// adds an element to the array if it does not already exist using a comparer
// function
Array.prototype.pushIfNotExist = function(element, comparer) {
    if (!this.inArray(comparer)) {
        this.push(element);
    }
};

// NI, GA, FUV, FEMEC, BIODIVERSIDADE -> 2 QUAD
// QUANTICA, BIOQUIMICA, EDS

var disciplinas_ideal = [
  'BCM0504-15',
  'BCN0404-15',
  'BCN0402-15',
  'BCJ0204-15',
  'BCL0306-15',
  'BCK0103-15',
  'BCL0308-15',
  'BIQ0602-15'
]

// atualiza as disciplinas para o quad ideal

router.get('/update_ideal', function (req, res, next) {
  // para cada discipina ideal faca
  for (var j = 0; j < disciplinas_ideal.length; j++) {
      Disciplina.find({codigo : disciplinas_ideal[j]}).exec(function (err, resp) {
        for (var i = 0; i < resp.length; i++) {
          resp[i].ideal_quad = true;
          resp[i].save();
        }
      })
  }
  res.json('OK');
});<|endoftext|>


<commit_before>// Require library
var Jimp = require('jimp');

module.exports.createTestImage = function(){
	var image = new Jimp(256, 256, function (err, image){
		//idk if i need this call back;
	});
	image.write("./output.png", function(err){
		console.log(err);
	})
}

module.exports.doesImageExists = function(){
	Jimp.read("./output.png", function (err, image){
		if(err){
			console.log("Image not tehre");
		}

	})
}<commit_msg>ok maybe needed to  be apromise or maybe because i wrote the filename wrong<commit_after>// Require library
var Jimp = require('jimp');

module.exports.createTestImage = function(){
	var image = new Jimp(256, 256, function (err, image){
		//idk if i need this call back;
	});
	image.write("./output.png", function(err){
		console.log(err);
	})
}

module.exports.doesImageExists = function(){
	Jimp.read("./output.png", function (err, image){
		if(err){
			console.log("Image not tehre");
			return;
		}
		console.log("Image is here?!?!?!?");

	})
}<|endoftext|>


<commit_before>'use strict';

require('comfychair/jasmine');
var comfy = require('comfychair');
var cbuf = require('ceci-buffers');
var chan = require('../index');
var channelSpec = require('./channels_spec');

var merge = function() {
  var args = Array.prototype.slice.call(arguments);
  var result = args.every(Array.isArray) ? [] : {};
  var i, obj, key;
  for (i in args) {
    obj = args[i];
    for (key in obj)
      result[key] = obj[key];
  }
  return result;
};

var randomList = function(minLen, maxLen, randomElement) {
  var n = comfy.randomInt(minLen, maxLen);
  var result = [];
  for (var i = 0; i < n; ++i)
    result.push(randomElement());
  return result;
};

var shrinkList = function(list, elementShrinker) {
  var result = [];
  var n = list.length;
  var i, head, tail;

  for (i = 0; i < n; ++i)
    result.push([].concat(list.slice(0, i), list.slice(i+1)));

  for (i = 0; i < n; ++i) {
    head = list.slice(0, i);
    tail = list.slice(i+1);
    elementShrinker(list[i]).forEach(function(x) {
      result.push([].concat(head, [x], tail));
    });
  }

  return result;
};

var shrinkObject = function(obj, shrinkers) {
  var result = [];

  for (var k in obj) {
    shrinkers[k](obj[k]).forEach(function(x) {
      var tmp = merge(obj);
      tmp[k] = x;
      result.push(tmp);
    });
  }

  return result;
};

var pack = function(list) {
  return list.map(function(x) { return [x]; });
};

var model = function() {
  var _tryCh = function(state, i, cmd, arg) {
    var result = state[i].channel.apply(state[i].state, cmd, [arg]);
    return {
      state: result.state,
      output: JSON.parse(result.output)
    };
  };

  var _makeResult = function(state, i, result) {
    var newState = state.slice();
    newState[i].state = result.state;
    return {
      state : newState,
      output: result.output
    };
  };

  var _applyCh = function(state, i, cmd, arg) {
    if (state.length == 0) {
      return {
        state : state,
        output: []
      };
    }

    i = i % state.length;
    return _makeResult(state, i, _tryCh(state, i, cmd, arg));
  };

  var _transitions = {
    init: function(state, descriptors) {
      return {
        state: descriptors.map(function(desc) {
          var channel = channelSpec.model(desc.type);
          var state   = channel.apply(null, 'init', [desc.size]).state;
          return {
            channel: channel,
            state  : state
          };
        })
      };
    },
    push: function(state, i, val) {
      return _applyCh(state, i, 'push', val);
    },
    pull: function(state, i) {
      return _applyCh(state, i, 'pull');
    },
    close: function(state, i) {
      return _applyCh(state, i, 'close');
    },
    select: function(state, cmds, defaultVal) {
      if (state.length > 0) {
        for (var i = 0; i < cmds.length; ++i) {
          var ch  = cmds[i].chan % state.length;
          var val = cmds[i].val;
          var cmd = val < 0 ? 'pull' : 'push';
          var res = _tryCh(state, ch, cmd, val);

          if (res.output.length > 0) {
            var result = _makeResult(state, ch, res);
            result.output = result.output.concat(ch);
            return result;
          }
        }
      }

      if (defaultVal < 0) {
        return {
          state : state,
          output: [-1, defaultVal]
        };
      } else {
        return {
          state: state,
          output: []
        };
      }
    }
  };

  var _genArgs = {
    init: function(size) {
      var k = Math.sqrt(size);
      var descriptors = randomList(0, k, function() {
        return {
          type: comfy.randomInt(0, 3),
          size: comfy.randomInt(0, k)
        };
      });
      return [descriptors];
    },
    push: function(size) {
      return [comfy.randomInt(0, size), comfy.randomInt(Math.sqrt(size))];
    },
    pull: function(size) {
      return [comfy.randomInt(0, size)];
    },
    close: function(size) {
      return [comfy.randomInt(0, size)];
    },
    select: function(size) {
      var k = Math.floor(Math.sqrt(size) / 2);
      var cmds = randomList(0, k, function() {
        return {
          chan: comfy.randomInt(0, size),
          val : comfy.randomInt(-k, k)
        };
      });
      var defaultVal = comfy.randomInt(-k, k);
      return [cmds, defaultVal];
    }
  };

  var _shrinkArgs = {
    init: function(args) {
      var shrinkers = {
        type: comfy.shrinkInt,
        size: comfy.shrinkInt
      };
      return pack(shrinkList(args[0], function(item) {
        return shrinkObject(item, shrinkers);
      }));
    },
    push: function(args) {
      return shrinkObject(args, [comfy.shrinkInt, comfy.shrinkInt]);
    },
    pull: function(args) {
      return pack(comfy.shrinkInt(args[0]));
    },
    close: function(args) {
      return pack(comfy.shrinkInt(args[0]));
    },
    select: function(args) {
      var cmdShrinkers = {
        chan: comfy.shrinkInt,
        val : comfy.shrinkInt
      };
      return shrinkObject(args, [
        function(cmds) {
          return shrinkList(cmds,
                            function(item) {
                              return shrinkObject(item, cmdShrinkers);
                            });
        },
        comfy.shrinkInt
      ]);
    }
  };

  return {
    commands: function() {
      var cmds = Object.keys(_transitions).slice();
      cmds.splice(cmds.indexOf('init'), 1);
      return cmds;
    },

    randomArgs: function(command, size) {
      return _genArgs[command](size);
    },

    shrinkArgs: function(command, args) {
      return _shrinkArgs[command](args);
    },

    apply: function(state, command, args) {
      var result = _transitions[command].apply(null, [state].concat(args));
      return {
        state : result.state,
        output: JSON.stringify(result.output)
      };
    }
  };
};

var implementation = function() {
  var _size, _channels;

  var _commands = {
    init: function(descriptors) {
      _size = descriptors.length;
      _channels = descriptors.map(function(desc) {
        var ch = channelSpec.implementation(desc.type);
        ch.apply('init', [desc.size]);
        return ch;
      });
    },
    push: function(i, val) {
      if (_size == 0)
        return [];
      return JSON.parse(_channels[i % _size].apply('push', [val]));
    },
    pull: function(i) {
      if (_size == 0)
        return [];
      return JSON.parse(_channels[i % _size].apply('pull', []));
    },
    close: function(i) {
      if (_size == 0)
        return [];
      return JSON.parse(_channels[i % _size].apply('close', []));
    },
    select: function(cmds, defaultVal) {
      var args;

      if (_size > 0) {
        args = cmds.map(function(cmd) {
          var ch  = _channels[cmd.chan % _size]._channel;
          var val = cmd.val;
          return val ? [ch, val] : ch;
        });
      } else
        args = [];

      var options = { priority: true };
      if (defaultVal < 0)
        options['default'] = defaultVal;

      var deferred = chan.select.apply(null, args.concat(options));

      if (deferred.isResolved()) {
        var result;

        deferred.then(function(output) {
          if (output.channel == null)
            result = [-1, output.value];
          else
            for (var i = 0; i < _size; ++i) {
              if (output.channel == _channels[i]._channel)
                result = [i, output.value];
            }
        });

        return result;
      } else
        return [];
    }
  };

  return {
    apply: function(command, args) {
      try {
        return JSON.stringify(_commands[command].apply(null, args));
      } catch(ex) { console.error(ex.stack); }
    }
  };
};

describe('the select implementation', function() {
  it('conforms to the appropriate model', function() {
    expect(implementation()).toConformTo(model(), 100);
  });
});
<commit_msg>more fiddling with the select spec to try and make it work<commit_after>'use strict';

require('comfychair/jasmine');
var comfy = require('comfychair');
var cbuf = require('ceci-buffers');
var chan = require('../index');
var channelSpec = require('./channels_spec');

var merge = function() {
  var args = Array.prototype.slice.call(arguments);
  var result = args.every(Array.isArray) ? [] : {};
  var i, obj, key;
  for (i in args) {
    obj = args[i];
    for (key in obj)
      result[key] = obj[key];
  }
  return result;
};

var randomList = function(minLen, maxLen, randomElement) {
  var n = comfy.randomInt(minLen, maxLen);
  var result = [];
  for (var i = 0; i < n; ++i)
    result.push(randomElement());
  return result;
};

var shrinkList = function(list, elementShrinker) {
  var result = [];
  var n = list.length;
  var i, head, tail;

  for (i = 0; i < n; ++i)
    result.push([].concat(list.slice(0, i), list.slice(i+1)));

  for (i = 0; i < n; ++i) {
    head = list.slice(0, i);
    tail = list.slice(i+1);
    elementShrinker(list[i]).forEach(function(x) {
      result.push([].concat(head, [x], tail));
    });
  }

  return result;
};

var shrinkObject = function(obj, shrinkers) {
  var result = [];

  for (var k in obj) {
    shrinkers[k](obj[k]).forEach(function(x) {
      var tmp = merge(obj);
      tmp[k] = x;
      result.push(tmp);
    });
  }

  return result;
};

var pack = function(list) {
  return list.map(function(x) { return [x]; });
};

var model = function() {
  var _tryCh = function(state, i, cmd, arg) {
    var result = state[i].channel.apply(state[i].state, cmd, [arg]);
    return {
      state: result.state,
      output: JSON.parse(result.output)
    };
  };

  var _makeResult = function(state, i, result) {
    var newState = state.slice();
    newState[i].state = result.state;
    return {
      state : newState,
      output: result.output
    };
  };

  var _applyCh = function(state, i, cmd, arg) {
    if (state.length == 0) {
      return {
        state : state,
        output: []
      };
    }

    i = i % state.length;
    return _makeResult(state, i, _tryCh(state, i, cmd, arg));
  };

  var _transitions = {
    init: function(state, descriptors) {
      return {
        state: descriptors.map(function(desc) {
          var channel = channelSpec.model(desc.type);
          var state   = channel.apply(null, 'init', [desc.size]).state;
          return {
            channel: channel,
            state  : state
          };
        })
      };
    },
    push: function(state, i, val) {
      return _applyCh(state, i, 'push', val);
    },
    pull: function(state, i) {
      return _applyCh(state, i, 'pull');
    },
    close: function(state, i) {
      return _applyCh(state, i, 'close');
    },
    select: function(state, cmds, defaultVal) {
      if (state.length > 0) {
        for (var i = 0; i < cmds.length; ++i) {
          var ch  = cmds[i].chan % state.length;
          var val = cmds[i].val;
          var cmd = val < 0 ? 'pull' : 'push';
          var res = _tryCh(state, ch, cmd, val);

          if (res.output.length > 0) {
            var result = _makeResult(state, ch, res);
            result.output = [ch, val < 0 ? result.output[0][1] : true];
            return result;
          }
        }
      }

      if (defaultVal < 0) {
        return {
          state : state,
          output: [-1, defaultVal]
        };
      } else {
        return {
          state: state,
          output: []
        };
      }
    }
  };

  var _genArgs = {
    init: function(size) {
      var k = Math.sqrt(size);
      var descriptors = randomList(0, k, function() {
        return {
          type: comfy.randomInt(0, 3),
          size: comfy.randomInt(0, k)
        };
      });
      return [descriptors];
    },
    push: function(size) {
      return [comfy.randomInt(0, size), comfy.randomInt(Math.sqrt(size))];
    },
    pull: function(size) {
      return [comfy.randomInt(0, size)];
    },
    close: function(size) {
      return [comfy.randomInt(0, size)];
    },
    select: function(size) {
      var k = Math.floor(Math.sqrt(size) / 2);
      var cmds = randomList(0, k, function() {
        return {
          chan: comfy.randomInt(0, size),
          val : comfy.randomInt(-k, k)
        };
      });
      var defaultVal = comfy.randomInt(-k, k);
      return [cmds, defaultVal];
    }
  };

  var _shrinkArgs = {
    init: function(args) {
      var shrinkers = {
        type: comfy.shrinkInt,
        size: comfy.shrinkInt
      };
      return pack(shrinkList(args[0], function(item) {
        return shrinkObject(item, shrinkers);
      }));
    },
    push: function(args) {
      return shrinkObject(args, [comfy.shrinkInt, comfy.shrinkInt]);
    },
    pull: function(args) {
      return pack(comfy.shrinkInt(args[0]));
    },
    close: function(args) {
      return pack(comfy.shrinkInt(args[0]));
    },
    select: function(args) {
      var cmdShrinkers = {
        chan: comfy.shrinkInt,
        val : comfy.shrinkInt
      };
      return shrinkObject(args, [
        function(cmds) {
          return shrinkList(cmds,
                            function(item) {
                              return shrinkObject(item, cmdShrinkers);
                            });
        },
        comfy.shrinkInt
      ]);
    }
  };

  return {
    commands: function() {
      var cmds = Object.keys(_transitions).slice();
      cmds.splice(cmds.indexOf('init'), 1);
      return cmds;
    },

    randomArgs: function(command, size) {
      return _genArgs[command](size);
    },

    shrinkArgs: function(command, args) {
      return _shrinkArgs[command](args);
    },

    apply: function(state, command, args) {
      var result = _transitions[command].apply(null, [state].concat(args));
      return {
        state : result.state,
        output: JSON.stringify(result.output)
      };
    }
  };
};

var implementation = function() {
  var _size, _channels;

  var _commands = {
    init: function(descriptors) {
      _size = descriptors.length;
      _channels = descriptors.map(function(desc) {
        var ch = channelSpec.implementation(desc.type);
        ch.apply('init', [desc.size]);
        return ch;
      });
    },
    push: function(i, val) {
      if (_size == 0)
        return [];
      return JSON.parse(_channels[i % _size].apply('push', [val]));
    },
    pull: function(i) {
      if (_size == 0)
        return [];
      return JSON.parse(_channels[i % _size].apply('pull', []));
    },
    close: function(i) {
      if (_size == 0)
        return [];
      return JSON.parse(_channels[i % _size].apply('close', []));
    },
    select: function(cmds, defaultVal) {
      var args;

      if (_size > 0) {
        args = cmds.map(function(cmd) {
          var ch  = _channels[cmd.chan % _size]._channel;
          var val = cmd.val;
          return val >= 0 ? [ch, val] : ch;
        });
      } else
        args = [];

      var options = { priority: true };
      if (defaultVal < 0)
        options['default'] = defaultVal;

      var deferred = chan.select.apply(null, args.concat(options));

      if (deferred.isResolved()) {
        var result;

        deferred.then(function(output) {
          if (output.channel == null)
            result = [-1, output.value];
          else
            for (var i = 0; i < _size; ++i) {
              if (output.channel == _channels[i]._channel)
                result = [i, output.value];
            }
        });

        return result;
      } else
        return [];
    }
  };

  return {
    apply: function(command, args) {
      try {
        return JSON.stringify(_commands[command].apply(null, args));
      } catch(ex) { console.error(ex.stack); }
    }
  };
};

describe('the select implementation', function() {
  it('conforms to the appropriate model', function() {
    expect(implementation()).toConformTo(model(), 100);
  });
});
<|endoftext|>


<commit_before>/**
 * External dependencies
 */
import { get } from 'lodash';
import PropTypes from 'prop-types';

/**
 * WordPress dependencies
 */
import { Component, createRef, renderToString } from '@wordpress/element';
import { Icon, IconButton } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { withSelect, withDispatch } from '@wordpress/data';
import { DotTip } from '@wordpress/nux';
import { compose } from '@wordpress/compose';
import { addQueryArgs } from '@wordpress/url';

/**
 * Internal dependencies
 */
import ampBlackIcon from '../../../images/amp-black-icon.svg';
import ampFilledIcon from '../../../images/amp-icon.svg';
import { isAMPEnabled } from '../helpers';
import { POST_PREVIEW_CLASS } from '../constants';

/**
 * Writes the message and graphic in the new preview window that was opened.
 *
 * Forked from the Core component <PostPreviewButton>.
 *
 * @see https://github.com/WordPress/gutenberg/blob/95e769df1f82f6b0ef587d81af65dd2f48cd1c38/packages/editor/src/components/post-preview-button/index.js#L17
 * @param {Object} targetDocument The target document.
 */
function writeInterstitialMessage( targetDocument ) {
	let markup = renderToString(

			<Icon
				icon={ ampBlackIcon( { viewBox: '0 0 98 98' } ) }
			/>

				{ __( 'Generating AMP preview…', 'amp' ) }

,
	);

	markup += `

	`;

	targetDocument.write( markup );
	targetDocument.title = __( 'Generating AMP preview…', 'amp' );
	targetDocument.close();
}

/**
 * A 'Preview AMP' button, forked from the Core 'Preview' button: <PostPreviewButton>.
 *
 * Rendered into the DOM with renderPreviewButton() in helpers/index.js.
 * This also moves the (non-AMP) 'Preview' button to before this, if it's not already there.
 *
 * @see https://github.com/WordPress/gutenberg/blob/95e769df1f82f6b0ef587d81af65dd2f48cd1c38/packages/editor/src/components/post-preview-button/index.js
 */
class AMPPreview extends Component {
	/**
	 * Constructs the class.
	 *
	 * @param {*} args Constructor arguments.
	 */
	constructor( ...args ) {
		super( ...args );
		this.moveButton = this.moveButton.bind( this );
		this.openPreviewWindow = this.openPreviewWindow.bind( this );
		this.buttonRef = createRef();
	}

	/**
	 * Called after the component is updated.
	 *
	 * @param {Object} prevProps The previous props.
	 */
	componentDidUpdate( prevProps ) {
		const { previewLink } = this.props;

		// This relies on the window being responsible to unset itself when
		// navigation occurs or a new preview window is opened, to avoid
		// unintentional forceful redirects.
		if ( previewLink && ! prevProps.previewLink ) {
			this.setPreviewWindowLink( previewLink );
		}

		this.moveButton();
	}

	/**
	 * Moves the (non-AMP) 'Preview' button to before this 'Preview AMP' button, if it's not there already.
	 */
	moveButton() {
		const buttonWrapper = get( this, [ 'buttonRef', 'current', 'parentNode' ], false );
		if ( ! buttonWrapper ) {
			return;
		}

		if ( ! buttonWrapper.previousSibling || ! buttonWrapper.previousSibling.classList.contains( POST_PREVIEW_CLASS ) ) {
			const postPreviewButton = document.querySelector( `.${ POST_PREVIEW_CLASS }` );
			if ( get( postPreviewButton, 'nextSibling' ) ) {
				buttonWrapper.parentNode.insertBefore( buttonWrapper, postPreviewButton.nextSibling );
			}
		}
	}

	/**
	 * Sets the preview window's location to the given URL, if a preview window
	 * exists and is not closed.
	 *
	 * @param {string} url URL to assign as preview window location.
	 */
	setPreviewWindowLink( url ) {
		const { previewWindow } = this;

		if ( previewWindow && ! previewWindow.closed ) {
			previewWindow.location = url;
		}
	}

	/**
	 * Gets the window target.
	 */
	getWindowTarget() {
		const { postId } = this.props;
		return `wp-preview-${ postId }`;
	}

	/**
	 * Opens the preview window.
	 *
	 * @param {Object} event The DOM event.
	 */
	openPreviewWindow( event ) {
		// Our Preview button has its 'href' and 'target' set correctly for a11y
		// purposes. Unfortunately, though, we can't rely on the default 'click'
		// handler since sometimes it incorrectly opens a new tab instead of reusing
		// the existing one.
		// https://github.com/WordPress/gutenberg/pull/8330
		event.preventDefault();

		// Open up a Preview tab if needed. This is where we'll show the preview.
		if ( ! this.previewWindow || this.previewWindow.closed ) {
			this.previewWindow = window.open( '', this.getWindowTarget() );
		}

		// Focus the Preview tab. This might not do anything, depending on the browser's
		// and user's preferences.
		// https://html.spec.whatwg.org/multipage/interaction.html#dom-window-focus
		this.previewWindow.focus();

		// If we don't need to autosave the post before previewing, then we simply
		// load the Preview URL in the Preview tab.
		if ( ! this.props.isAutosaveable ) {
			this.setPreviewWindowLink( event.target.href );
			return;
		}

		// Request an autosave. This happens asynchronously and causes the component
		// to update when finished.
		if ( this.props.isDraft ) {
			this.props.savePost( { isPreview: true } );
		} else {
			this.props.autosave( { isPreview: true } );
		}

		// Display a 'Generating preview' message in the Preview tab while we wait for the
		// autosave to finish.
		writeInterstitialMessage( this.previewWindow.document );
	}

	/**
	 * Renders the component.
	 */
	render() {
		const { previewLink, currentPostLink, errorMessages, isEnabled, isSaveable, isStandardMode } = this.props;

		// Link to the `?preview=true` URL if we have it, since this lets us see
		// changes that were autosaved since the post was last published. Otherwise,
		// just link to the post's URL.
		const href = previewLink || currentPostLink;

		return (
			isEnabled && ! errorMessages.length && ! isStandardMode && (
				<IconButton
					icon={ ampFilledIcon( { viewBox: '0 0 62 62' } ) }
					isLarge
					className="amp-editor-post-preview"
					href={ href }
					label={ __( 'Preview AMP', 'amp' ) }
					target={ this.getWindowTarget() }
					disabled={ ! isSaveable }
					onClick={ this.openPreviewWindow }
					ref={ this.buttonRef }
				>

						{
							/* translators: accessibility text */
							__( '(opens in a new tab)', 'amp' )
						}

					<DotTip tipId="amp/editor.preview">
						{ __( 'Click “Preview” to load a preview of this page in AMP, so you can make sure you are happy with your blocks.', 'amp' ) }
					</DotTip>
				</IconButton>
			)
		);
	}
}

AMPPreview.propTypes = {
	autosave: PropTypes.func.isRequired,
	currentPostLink: PropTypes.string.isRequired,
	postId: PropTypes.number.isRequired,
	previewLink: PropTypes.string,
	isAutosaveable: PropTypes.bool.isRequired,
	isDraft: PropTypes.bool.isRequired,
	isEnabled: PropTypes.bool.isRequired,
	isSaveable: PropTypes.bool.isRequired,
	savePost: PropTypes.func.isRequired,
	errorMessages: PropTypes.array,
	isStandardMode: PropTypes.bool,
};

export default compose( [
	withSelect( ( select, { forcePreviewLink, forceIsAutosaveable } ) => {
		const {
			getCurrentPostId,
			getCurrentPostAttribute,
			getEditedPostAttribute,
			isEditedPostSaveable,
			isEditedPostAutosaveable,
			getEditedPostPreviewLink,
		} = select( 'core/editor' );

		const {
			getAmpSlug,
			getErrorMessages,
			isStandardMode,
		} = select( 'amp/block-editor' );

		const queryArgs = {};
		queryArgs[ getAmpSlug() ] = 1;
		const initialPreviewLink = getEditedPostPreviewLink();
		const previewLink = initialPreviewLink ? addQueryArgs( initialPreviewLink, queryArgs ) : undefined;

		return {
			postId: getCurrentPostId(),
			currentPostLink: addQueryArgs( getCurrentPostAttribute( 'link' ), queryArgs ),
			previewLink: forcePreviewLink !== undefined ? forcePreviewLink : previewLink,
			isSaveable: isEditedPostSaveable(),
			isAutosaveable: forceIsAutosaveable || isEditedPostAutosaveable(),
			isDraft: [ 'draft', 'auto-draft' ].indexOf( getEditedPostAttribute( 'status' ) ) !== -1,
			isEnabled: isAMPEnabled(),
			errorMessages: getErrorMessages(),
			isStandardMode: isStandardMode(),
		};
	} ),
	withDispatch( ( dispatch ) => ( {
		autosave: dispatch( 'core/editor' ).autosave,
		savePost: dispatch( 'core/editor' ).savePost,
	} ) ),
] )( AMPPreview );
<commit_msg>Fix an issue where clicking the non-AMP preview button reloads the AMP preview<commit_after>/**
 * External dependencies
 */
import { get } from 'lodash';
import PropTypes from 'prop-types';

/**
 * WordPress dependencies
 */
import { Component, createRef, renderToString } from '@wordpress/element';
import { Icon, IconButton } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { withSelect, withDispatch } from '@wordpress/data';
import { DotTip } from '@wordpress/nux';
import { compose } from '@wordpress/compose';
import { addQueryArgs } from '@wordpress/url';

/**
 * Internal dependencies
 */
import ampBlackIcon from '../../../images/amp-black-icon.svg';
import ampFilledIcon from '../../../images/amp-icon.svg';
import { isAMPEnabled } from '../helpers';
import { POST_PREVIEW_CLASS } from '../constants';

/**
 * Writes the message and graphic in the new preview window that was opened.
 *
 * Forked from the Core component <PostPreviewButton>.
 *
 * @see https://github.com/WordPress/gutenberg/blob/95e769df1f82f6b0ef587d81af65dd2f48cd1c38/packages/editor/src/components/post-preview-button/index.js#L17
 * @param {Object} targetDocument The target document.
 */
function writeInterstitialMessage( targetDocument ) {
	let markup = renderToString(

			<Icon
				icon={ ampBlackIcon( { viewBox: '0 0 98 98' } ) }
			/>

				{ __( 'Generating AMP preview…', 'amp' ) }

,
	);

	markup += `

	`;

	targetDocument.write( markup );
	targetDocument.title = __( 'Generating AMP preview…', 'amp' );
	targetDocument.close();
}

/**
 * A 'Preview AMP' button, forked from the Core 'Preview' button: <PostPreviewButton>.
 *
 * Rendered into the DOM with renderPreviewButton() in helpers/index.js.
 * This also moves the (non-AMP) 'Preview' button to before this, if it's not already there.
 *
 * @see https://github.com/WordPress/gutenberg/blob/95e769df1f82f6b0ef587d81af65dd2f48cd1c38/packages/editor/src/components/post-preview-button/index.js
 */
class AMPPreview extends Component {
	/**
	 * Constructs the class.
	 *
	 * @param {*} args Constructor arguments.
	 */
	constructor( ...args ) {
		super( ...args );
		this.moveButton = this.moveButton.bind( this );
		this.openPreviewWindow = this.openPreviewWindow.bind( this );
		this.buttonRef = createRef();
	}

	/**
	 * Called after the component is updated.
	 *
	 * @param {Object} prevProps The previous props.
	 */
	componentDidUpdate( prevProps ) {
		const { previewLink } = this.props;

		// This relies on the window being responsible to unset itself when
		// navigation occurs or a new preview window is opened, to avoid
		// unintentional forceful redirects.
		if ( previewLink && ! prevProps.previewLink ) {
			this.setPreviewWindowLink( previewLink );
		}

		this.moveButton();
	}

	/**
	 * Moves the (non-AMP) 'Preview' button to before this 'Preview AMP' button, if it's not there already.
	 */
	moveButton() {
		const buttonWrapper = get( this, [ 'buttonRef', 'current', 'parentNode' ], false );
		if ( ! buttonWrapper ) {
			return;
		}

		if ( ! buttonWrapper.previousSibling || ! buttonWrapper.previousSibling.classList.contains( POST_PREVIEW_CLASS ) ) {
			const postPreviewButton = document.querySelector( `.${ POST_PREVIEW_CLASS }` );
			if ( get( postPreviewButton, 'nextSibling' ) ) {
				buttonWrapper.parentNode.insertBefore( buttonWrapper, postPreviewButton.nextSibling );
			}
		}
	}

	/**
	 * Sets the preview window's location to the given URL, if a preview window
	 * exists and is not closed.
	 *
	 * @param {string} url URL to assign as preview window location.
	 */
	setPreviewWindowLink( url ) {
		const { previewWindow } = this;

		if ( previewWindow && ! previewWindow.closed ) {
			previewWindow.location = url;
		}
	}

	/**
	 * Gets the window target.
	 */
	getWindowTarget() {
		const { postId } = this.props;
		return `amp-preview-${ postId }`;
	}

	/**
	 * Opens the preview window.
	 *
	 * @param {Object} event The DOM event.
	 */
	openPreviewWindow( event ) {
		// Our Preview button has its 'href' and 'target' set correctly for a11y
		// purposes. Unfortunately, though, we can't rely on the default 'click'
		// handler since sometimes it incorrectly opens a new tab instead of reusing
		// the existing one.
		// https://github.com/WordPress/gutenberg/pull/8330
		event.preventDefault();

		// Open up a Preview tab if needed. This is where we'll show the preview.
		if ( ! this.previewWindow || this.previewWindow.closed ) {
			this.previewWindow = window.open( '', this.getWindowTarget() );
		}

		// Focus the Preview tab. This might not do anything, depending on the browser's
		// and user's preferences.
		// https://html.spec.whatwg.org/multipage/interaction.html#dom-window-focus
		this.previewWindow.focus();

		// If we don't need to autosave the post before previewing, then we simply
		// load the Preview URL in the Preview tab.
		if ( ! this.props.isAutosaveable ) {
			this.setPreviewWindowLink( event.target.href );
			return;
		}

		// Request an autosave. This happens asynchronously and causes the component
		// to update when finished.
		if ( this.props.isDraft ) {
			this.props.savePost( { isPreview: true } );
		} else {
			this.props.autosave( { isPreview: true } );
		}

		// Display a 'Generating preview' message in the Preview tab while we wait for the
		// autosave to finish.
		writeInterstitialMessage( this.previewWindow.document );
	}

	/**
	 * Renders the component.
	 */
	render() {
		const { previewLink, currentPostLink, errorMessages, isEnabled, isSaveable, isStandardMode } = this.props;

		// Link to the `?preview=true` URL if we have it, since this lets us see
		// changes that were autosaved since the post was last published. Otherwise,
		// just link to the post's URL.
		const href = previewLink || currentPostLink;

		return (
			isEnabled && ! errorMessages.length && ! isStandardMode && (
				<IconButton
					icon={ ampFilledIcon( { viewBox: '0 0 62 62' } ) }
					isLarge
					className="amp-editor-post-preview"
					href={ href }
					label={ __( 'Preview AMP', 'amp' ) }
					target={ this.getWindowTarget() }
					disabled={ ! isSaveable }
					onClick={ this.openPreviewWindow }
					ref={ this.buttonRef }
				>

						{
							/* translators: accessibility text */
							__( '(opens in a new tab)', 'amp' )
						}

					<DotTip tipId="amp/editor.preview">
						{ __( 'Click “Preview” to load a preview of this page in AMP, so you can make sure you are happy with your blocks.', 'amp' ) }
					</DotTip>
				</IconButton>
			)
		);
	}
}

AMPPreview.propTypes = {
	autosave: PropTypes.func.isRequired,
	currentPostLink: PropTypes.string.isRequired,
	postId: PropTypes.number.isRequired,
	previewLink: PropTypes.string,
	isAutosaveable: PropTypes.bool.isRequired,
	isDraft: PropTypes.bool.isRequired,
	isEnabled: PropTypes.bool.isRequired,
	isSaveable: PropTypes.bool.isRequired,
	savePost: PropTypes.func.isRequired,
	errorMessages: PropTypes.array,
	isStandardMode: PropTypes.bool,
};

export default compose( [
	withSelect( ( select, { forcePreviewLink, forceIsAutosaveable } ) => {
		const {
			getCurrentPostId,
			getCurrentPostAttribute,
			getEditedPostAttribute,
			isEditedPostSaveable,
			isEditedPostAutosaveable,
			getEditedPostPreviewLink,
		} = select( 'core/editor' );

		const {
			getAmpSlug,
			getErrorMessages,
			isStandardMode,
		} = select( 'amp/block-editor' );

		const queryArgs = {};
		queryArgs[ getAmpSlug() ] = 1;
		const initialPreviewLink = getEditedPostPreviewLink();
		const previewLink = initialPreviewLink ? addQueryArgs( initialPreviewLink, queryArgs ) : undefined;

		return {
			postId: getCurrentPostId(),
			currentPostLink: addQueryArgs( getCurrentPostAttribute( 'link' ), queryArgs ),
			previewLink: forcePreviewLink !== undefined ? forcePreviewLink : previewLink,
			isSaveable: isEditedPostSaveable(),
			isAutosaveable: forceIsAutosaveable || isEditedPostAutosaveable(),
			isDraft: [ 'draft', 'auto-draft' ].indexOf( getEditedPostAttribute( 'status' ) ) !== -1,
			isEnabled: isAMPEnabled(),
			errorMessages: getErrorMessages(),
			isStandardMode: isStandardMode(),
		};
	} ),
	withDispatch( ( dispatch ) => ( {
		autosave: dispatch( 'core/editor' ).autosave,
		savePost: dispatch( 'core/editor' ).savePost,
	} ) ),
] )( AMPPreview );
<|endoftext|>