<commit_before>/**
 * WP Present - admin.js
 *
 */

var WPPresentAdmin;
(function($) {

	WPPresentAdmin = function() {
		this.init();
		return this;
	}

	WPPresentAdmin.prototype = {
		init: function() {
			var self = this;

			self.widgetButtonExpand();
			self.widgetButtonEdit();
			self.widgetButtonDelete();
			self.widgetButtonAdd();
			self.widgetButtonTidy();
			self.bindButtonAddColumn();
			self.bindButtonViewPresentation();
			self.uiSetup();

			// Select the first column on load
			self.activateColumn( $('#col-1').children('.widget-top').children('.widget-title') );

			return self;
		},

		// Sortables and such
		uiSetup: function () {
			var self = this;

			// Make the outer container resizeable
			$( "#outer-container" ).resizable();

			self.backfillSlides();

			$( ".column-inner" ).sortable({
				connectWith: ".column-inner",
				stop: function( event, ui ) {
					self.updateColumns();
				}
			});

			$( "#container" ).sortable({
				stop: function( event, ui ) {
					self.updateColumns();
				}
			});

			self.updateColumns();
			$( ".column-inner" ).disableSelection();

			// Append an inner column to each column that doesn't contain any slides.
			jQuery('.column' ).not(":has(div.column-inner)").append('

');

			$( ".column-inner" ).sortable({
				connectWith: ".column-inner",
				stop: function( event, ui ) {
					self.updateColumns();
				}
			});

			self.columnHandle();
		},

		/**
		 * Close Modal
		 */
		closeModal: function() {
			tinymce.execCommand('mceRemoveControl',true,'editor_slide');
			$( '#dialog' ).dialog( "close" );
		},

		/**
		 * Backfill Slides
		 */
		backfillSlides: function () {
			var self = this;
			var numSlides = WPPNumSlides;
			var numExisting = $('#container > .column').size();

			for (var col=numExisting+1;col<=numSlides;col++){
				self.addColumn();
			}
			//$('#container').append( '

' );
		},

		/**
		 * Make the column the target for adding new columns
		 */
		activateColumn: function ( $col ) {
			// Remove the active class from all columns
			$('.widget-title').css('background', '');
			$('.widget-title').css('color', '');
			$('.widget-title').removeClass('active');

			// Select the given column
			$col.css('background-color', '#2ea2cc').css('color','#ffffff');
			$col.addClass('active');
		},

		/**
		 * update columns
		 */
		updateColumns: function () {
			var self = this;
			var columns = { }; // Creates a new object
			var i = 1;
			$( '.column-inner' ).each(function( index ) {
				var $order = $(this).sortable( "toArray" );
				columns['col-'+i] = $order;
				i++;
			});
			var encoded = JSON.stringify( columns );
			$('#description').val(encoded);

			self.renumberColumns();

			// Send this change off to ajax land
			self.updatePresentation();
		},

//Dude this is not okay. Fix the post data ajax call

		/**
		 * AJAX request to update the current presentation taxonomy
		 */
		updatePresentation: function () {
			var nonce = $('#wp-present-nonce').val();
			var params = { content: $('#description').val() };
			$.ajax({
				url: ajaxurl + '?action=update_presentation&id=' + presentation + '&nonce=' + nonce,
				type: 'POST',
				data: jQuery.param(params),
				beforeSend: function( xhr ) {
					$('.spinner').show();
				},
				complete: function( xhr ) {
					$('.spinner').hide();
				},
				success: function(result) {
					// Return the excerpt from the editor
					//console.log('presentation updated');
				}
			});
		},

		/**
		 * Bind Tidy button
		 */
		widgetButtonTidy: function () {
			var self = this;
			$('.action-buttons').on('click', '#tidy-button', function(e) {
				e.preventDefault();
				this.consolidateColumns();
				// Why does this break?
				//updatePresentation();
			});
		},

		/**
		 * Expand slide details
		 */
		widgetButtonExpand: function () {
			$('.column').on('click', '.widget-title-action', function(e) {
				$( this ).parents('.widget').children('.widget-inside').toggle();
			});
		},

		/**
		 * The action taken by the Tidy button
		 */
		consolidateColumns: function () {
			var self = this;
			var numCols = $('.column').length;
			// console.log(numCols);

			$('.column').each(function(outerIndex){

				// Don't have a col 0
				var outerIndex = outerIndex + 1;

				// Fixes the condition where we are looking at the last item
				if( outerIndex >= numCols )
					return;

				var $outerCol = $(this);
				var $innerCol = $outerCol.children('.column-inner');

				var innerHTML = $innerCol.html().trim();
				var outerHTML = $outerCol.html().trim();

				if( typeof(innerHTML) !== 'string' || '' == innerHTML ) {
					var $nextOuterCol = $('#col-'+(outerIndex+1));
					var $nextInnerCol = $nextOuterCol.children('.column-inner');

					var nextInnerHTML = $nextInnerCol.html().trim();
					var nextOuterHTML = $nextOuterCol.html().trim();

					$outerCol.html(nextOuterHTML);
					$nextOuterCol.html(outerHTML);
				}
			} );

			//Finally refresh description array
			$( ".column-inner" ).sortable({
				connectWith: ".column-inner",
				stop: (function( event, ui ) {
					self.updateColumns();
				}),
				create: (function( event, ui ) {
					self.updateColumns();
				})
			});
			self.updateColumns();
		},

		columnHandle: function () {
			var self = this;
			$('.column').children('.widget-top').on('click', '.widget-title', function(e) {
				$col = $(this);
				self.activateColumn($col);
			});
		},

		// Bind Edit button
		widgetButtonEdit: function () {
			var self = this;
			$('.column').on('click', '.widget-control-edit', function(e) {
				e.preventDefault();
				var $button = $(this);
				var $parentWidget = $button.parents('.widget');
				var $widgetPreview = $parentWidget.find('.widget-preview');

				// Send the contents from the widget to the editor
				var contentEditor  = $widgetPreview.html();
				var widgetID = $parentWidget.find('.slide-id').val();
				var nonce = $('#wp-present-nonce').val();
//Dude this is not okay. Fix the post data ajax call
				$('#editor_slide-tmce').click(); //Necessary on subsequent loads of the editor
				$( "#dialog" ).dialog({
				  autoOpen: true,
				  width: 640,
				  height: 640,
				  modal: false,
				  buttons: {
					"Update": function() {
						var editorContents = tinymce.get('editor_slide').getContent();
						var params = { content:editorContents };
						// Send the contents of the existing post
						$.ajax({
							url: ajaxurl + '?action=update_slide&id=' + widgetID + '&nonce=' + nonce,
							type: 'POST',
							data: jQuery.param(params),
							beforeSend: function( xhr ) {
								$('.spinner').show();
							},
							complete: function( xhr ) {
								$('.spinner').hide();
							},
							success: function(result) {
								// Return the excerpt from the editor
								$widgetPreview.html( result );
						  }
						});
						self.closeModal();
					},
					Cancel: function() {
						self.closeModal();
					}
				  },
				  create: function() {
						tinymce.execCommand('mceRemoveControl',true,'editor_slide');
						tinymce.execCommand('mceAddControl',true,'editor_slide');
				  },
				  open: function() {
						// Load the contents of the existing post
						var nonce = $('#wp-present-nonce').val();
						$.ajax({
							url: ajaxurl + '?action=get_slide&id=' + widgetID + '&nonce=' + nonce,
							beforeSend: function( xhr ) {
								$('.spinner').show();
							},
							complete: function( xhr ) {
								$('.spinner').hide();
							},
							success: function(contentEditor) {
								tinymce.get('editor_slide').setContent(contentEditor);
							}
						});

						// Hack for getting the reveal class added to tinymce editor body
						// @todo: look at wp_editor in wp/inc/class-wp-editor.php
						var $editorIframe = $('#editor_slide_ifr').contents();
						$editorIframe.find('body').addClass('reveal');
						$editorIframe.css('height','500px');

				  },
				  close: function() {
						self.closeModal();
				  }
				});
			});
		},

		// Bind Delete button
		widgetButtonDelete: function () {
			var self = this;
			$('.column').on('click', '.widget-control-remove', function(e) {
				e.preventDefault();

				var confirmDelete = confirm("You are about to permanently delete the selected slide. 'Cancel' to stop, 'OK' to delete.");
				if( false == confirmDelete )
					return;

				var $button = $(this);
				var $parentWidget = $button.parents('.widget');
				var widgetID = $parentWidget.find('.slide-id').val();
				var nonce = $('#wp-present-nonce').val();
				var params = null;

				$.ajax({
					url: ajaxurl + '?action=delete_slide&id=' + widgetID + '&nonce=' + nonce,
					type: 'POST',
					//data: jQuery.param(params),
					beforeSend: function( xhr ) {
						$('.spinner').show();
					},
					complete: function( xhr ) {
						$('.spinner').hide();
					},
					success: function(result) {
						$parentWidget.remove();
						self.updateColumns();
					}
				});
			});
		},

		// Bind Add button
		widgetButtonAdd: function () {
			var self = this;
			$('.action-buttons').on('click', '#add-button', function(e) {
				e.preventDefault();
				var $button = $(this);
				var $activeColumn = $('.widget-title.active').parent('.widget-top').parent('.column').children('.column-inner');

				$('#editor_slide-tmce').click(); //Necessary on subsequent loads of the editor
				$( "#dialog" ).dialog({
				  autoOpen: true,
				  width: 600,
				  height: 600,
				  modal: false,
				  buttons: {
					"Publish": function() {
						var editorContents = tinymce.get('editor_slide').getContent();
						var nonce = $('#wp-present-nonce').val();
						var params = { content:editorContents };
						// Send the contents of the existing post
						$.ajax({
							url: ajaxurl + '?action=new_slide&presentation=' + presentation + '&nonce=' + nonce,
							type: 'POST',
							data: jQuery.param(params),
							success: function(result) {
								$activeColumn.append(result);
								self.addColumn();
								self.updateColumns();
						  }
						});
						self.updateColumns();
						self.closeModal();
					},
					Cancel: function() {
						self.closeModal();
					}
				  },
				  create: function() {
						tinymce.execCommand('mceRemoveControl',true,'editor_slide');
						tinymce.execCommand('mceAddControl',true,'editor_slide');
				  },
				  open: function() {
						// Clear the editor
						tinymce.get('editor_slide').setContent('');
						// Hack for getting the reveal class added to tinymce editor body
						var $editorIframe = $('#editor_slide_ifr').contents();
						$editorIframe.find('body').addClass('reveal');
				  },
				  close: function() {
						self.closeModal();
				  }
				});
			});
		},

		// Adds a column to the presentation
		addColumn: function () {
			var self = this;
			var col = $('#container > .column').size() + 1;

			$('#container').append( '

'+col+'

' );
			$('#container').width( $('#container').width() + 210 );

			// Make sure all is good in the world
			self.uiSetup();

			// Send this change off to ajax land
			self.updatePresentation();

			WPPNumSlides++;
		},

		//Bind Add Column button to addColumn()
		bindButtonAddColumn: function () {
			var self = this;
			$('.action-buttons').on('click', '#add-column', function(e) {
				e.preventDefault();
				self.addColumn();
			});
		},

		//Bind View Presentation button
		bindButtonViewPresentation: function () {
			var self = this;
			$('.action-buttons').on('click', '#view-button', function(e) {
				e.preventDefault();
				window.open(WPPTaxonomyURL,'_blank');
			});
		},

		renumberColumns: function() {
			var i = 1;
			$( '.column' ).each(function( index ) {
				 var self = this;
				 var $self = $(this);
				 $self.find('> .widget-top > .widget-title > h4').html( i );
				i++;
			});
		}

	};

})(jQuery);
var slideManager = new WPPresentAdmin();<commit_msg>Resolves a nasty recursion loop in JS<commit_after>/**
 * WP Present - admin.js
 *
 */

var WPPresentAdmin;
(function($) {

	WPPresentAdmin = function() {
		this.init();
		return this;
	}

	WPPresentAdmin.prototype = {
		init: function() {
			var self = this;

			self.widgetButtonExpand();
			self.widgetButtonEdit();
			self.widgetButtonDelete();
			self.widgetButtonAdd();
			self.widgetButtonTidy();
			self.bindButtonAddColumn();
			self.bindButtonViewPresentation();
			self.uiSetup();

			// Select the first column on load
			self.activateColumn( $('#col-1').children('.widget-top').children('.widget-title') );

			return self;
		},

		// Sortables and such
		uiSetup: function () {
			var self = this;

			self.backfillSlides();

			// Make the outer container resizeable
			$( "#outer-container" ).resizable();

			$( ".column-inner" ).sortable({
				connectWith: ".column-inner",
				stop: function( event, ui ) {
					self.updateColumns();
				}
			});

			$( "#container" ).sortable({
				stop: function( event, ui ) {
					self.updateColumns();
				}
			});

			self.updateColumns();
			$( ".column-inner" ).disableSelection();

			// Append an inner column to each column that doesn't contain any slides.
			jQuery('.column' ).not(":has(div.column-inner)").append('

');

			$( ".column-inner" ).sortable({
				connectWith: ".column-inner",
				stop: function( event, ui ) {
					self.updateColumns();
				}
			});

			self.columnHandle();
		},

		/**
		 * Close Modal
		 */
		closeModal: function() {
			tinymce.execCommand('mceRemoveControl',true,'editor_slide');
			$( '#dialog' ).dialog( "close" );
		},

		/**
		 * Backfill Slides
		 */
		backfillSlides: function () {
			var self = this;
			var numSlides = WPPNumSlides[0];
			var numExisting = $('#container > .column').size();

			for (var col=numExisting+1;col<=numSlides;col++){
				self.addColumn();
			}
			//$('#container').append( '

' );
		},

		/**
		 * Make the column the target for adding new columns
		 */
		activateColumn: function ( $col ) {
			// Remove the active class from all columns
			$('.widget-title').css('background', '');
			$('.widget-title').css('color', '');
			$('.widget-title').removeClass('active');

			// Select the given column
			$col.css('background-color', '#2ea2cc').css('color','#ffffff');
			$col.addClass('active');
		},

		/**
		 * update columns
		 */
		updateColumns: function () {
			var self = this;
			var columns = { }; // Creates a new object
			var i = 1;
			$( '.column-inner' ).each(function( index ) {
				var $order = $(this).sortable( "toArray" );
				columns['col-'+i] = $order;
				i++;
			});
			var encoded = JSON.stringify( columns );
			$('#description').val(encoded);

			self.renumberColumns();

			// Send this change off to ajax land
			self.updatePresentation();
		},

//Dude this is not okay. Fix the post data ajax call

		/**
		 * AJAX request to update the current presentation taxonomy
		 */
		updatePresentation: function () {
			var nonce = $('#wp-present-nonce').val();
			var params = { content: $('#description').val() };
			$.ajax({
				url: ajaxurl + '?action=update_presentation&id=' + presentation + '&nonce=' + nonce,
				type: 'POST',
				data: jQuery.param(params),
				beforeSend: function( xhr ) {
					$('.spinner').show();
				},
				complete: function( xhr ) {
					$('.spinner').hide();
				},
				success: function(result) {
					// Return the excerpt from the editor
					//console.log('presentation updated');
				}
			});
		},

		/**
		 * Bind Tidy button
		 */
		widgetButtonTidy: function () {
			var self = this;
			$('.action-buttons').on('click', '#tidy-button', function(e) {
				e.preventDefault();
				this.consolidateColumns();
				// Why does this break?
				//updatePresentation();
			});
		},

		/**
		 * Expand slide details
		 */
		widgetButtonExpand: function () {
			$('.column').on('click', '.widget-title-action', function(e) {
				$( this ).parents('.widget').children('.widget-inside').toggle();
			});
		},

		/**
		 * The action taken by the Tidy button
		 */
		consolidateColumns: function () {
			var self = this;
			var numCols = $('.column').length;
			// console.log(numCols);

			$('.column').each(function(outerIndex){

				// Don't have a col 0
				var outerIndex = outerIndex + 1;

				// Fixes the condition where we are looking at the last item
				if( outerIndex >= numCols )
					return;

				var $outerCol = $(this);
				var $innerCol = $outerCol.children('.column-inner');

				var innerHTML = $innerCol.html().trim();
				var outerHTML = $outerCol.html().trim();

				if( typeof(innerHTML) !== 'string' || '' == innerHTML ) {
					var $nextOuterCol = $('#col-'+(outerIndex+1));
					var $nextInnerCol = $nextOuterCol.children('.column-inner');

					var nextInnerHTML = $nextInnerCol.html().trim();
					var nextOuterHTML = $nextOuterCol.html().trim();

					$outerCol.html(nextOuterHTML);
					$nextOuterCol.html(outerHTML);
				}
			} );

			//Finally refresh description array
			$( ".column-inner" ).sortable({
				connectWith: ".column-inner",
				stop: (function( event, ui ) {
					self.updateColumns();
				}),
				create: (function( event, ui ) {
					self.updateColumns();
				})
			});
			self.updateColumns();
		},

		columnHandle: function () {
			var self = this;
			$('.column').children('.widget-top').on('click', '.widget-title', function(e) {
				$col = $(this);
				self.activateColumn($col);
			});
		},

		// Bind Edit button
		widgetButtonEdit: function () {
			var self = this;
			$('.column').on('click', '.widget-control-edit', function(e) {
				e.preventDefault();
				var $button = $(this);
				var $parentWidget = $button.parents('.widget');
				var $widgetPreview = $parentWidget.find('.widget-preview');

				// Send the contents from the widget to the editor
				var contentEditor  = $widgetPreview.html();
				var widgetID = $parentWidget.find('.slide-id').val();
				var nonce = $('#wp-present-nonce').val();
//Dude this is not okay. Fix the post data ajax call
				$('#editor_slide-tmce').click(); //Necessary on subsequent loads of the editor
				$( "#dialog" ).dialog({
				  autoOpen: true,
				  width: 640,
				  height: 640,
				  modal: false,
				  buttons: {
					"Update": function() {
						var editorContents = tinymce.get('editor_slide').getContent();
						var params = { content:editorContents };
						// Send the contents of the existing post
						$.ajax({
							url: ajaxurl + '?action=update_slide&id=' + widgetID + '&nonce=' + nonce,
							type: 'POST',
							data: jQuery.param(params),
							beforeSend: function( xhr ) {
								$('.spinner').show();
							},
							complete: function( xhr ) {
								$('.spinner').hide();
							},
							success: function(result) {
								// Return the excerpt from the editor
								$widgetPreview.html( result );
						  }
						});
						self.closeModal();
					},
					Cancel: function() {
						self.closeModal();
					}
				  },
				  create: function() {
						tinymce.execCommand('mceRemoveControl',true,'editor_slide');
						tinymce.execCommand('mceAddControl',true,'editor_slide');
				  },
				  open: function() {
						// Load the contents of the existing post
						var nonce = $('#wp-present-nonce').val();
						$.ajax({
							url: ajaxurl + '?action=get_slide&id=' + widgetID + '&nonce=' + nonce,
							beforeSend: function( xhr ) {
								$('.spinner').show();
							},
							complete: function( xhr ) {
								$('.spinner').hide();
							},
							success: function(contentEditor) {
								tinymce.get('editor_slide').setContent(contentEditor);
							}
						});

						// Hack for getting the reveal class added to tinymce editor body
						// @todo: look at wp_editor in wp/inc/class-wp-editor.php
						var $editorIframe = $('#editor_slide_ifr').contents();
						$editorIframe.find('body').addClass('reveal');
						$editorIframe.css('height','500px');

				  },
				  close: function() {
						self.closeModal();
				  }
				});
			});
		},

		// Bind Delete button
		widgetButtonDelete: function () {
			var self = this;
			$('.column').on('click', '.widget-control-remove', function(e) {
				e.preventDefault();

				var confirmDelete = confirm("You are about to permanently delete the selected slide. 'Cancel' to stop, 'OK' to delete.");
				if( false == confirmDelete )
					return;

				var $button = $(this);
				var $parentWidget = $button.parents('.widget');
				var widgetID = $parentWidget.find('.slide-id').val();
				var nonce = $('#wp-present-nonce').val();
				var params = null;

				$.ajax({
					url: ajaxurl + '?action=delete_slide&id=' + widgetID + '&nonce=' + nonce,
					type: 'POST',
					//data: jQuery.param(params),
					beforeSend: function( xhr ) {
						$('.spinner').show();
					},
					complete: function( xhr ) {
						$('.spinner').hide();
					},
					success: function(result) {
						$parentWidget.remove();
						self.updateColumns();
					}
				});
			});
		},

		// Bind Add button
		widgetButtonAdd: function () {
			var self = this;
			$('.action-buttons').on('click', '#add-button', function(e) {
				e.preventDefault();
				var $button = $(this);
				var $activeColumn = $('.widget-title.active').parent('.widget-top').parent('.column').children('.column-inner');

				$('#editor_slide-tmce').click(); //Necessary on subsequent loads of the editor
				$( "#dialog" ).dialog({
				  autoOpen: true,
				  width: 600,
				  height: 600,
				  modal: false,
				  buttons: {
					"Publish": function() {
						var editorContents = tinymce.get('editor_slide').getContent();
						var nonce = $('#wp-present-nonce').val();
						var params = { content:editorContents };
						// Send the contents of the existing post
						$.ajax({
							url: ajaxurl + '?action=new_slide&presentation=' + presentation + '&nonce=' + nonce,
							type: 'POST',
							data: jQuery.param(params),
							success: function(result) {
								$activeColumn.append(result);
								self.addColumn();
								WPPNumSlides[0]++;
								self.updateColumns();
						  }
						});
						self.updateColumns();
						self.closeModal();
					},
					Cancel: function() {
						self.closeModal();
					}
				  },
				  create: function() {
						tinymce.execCommand('mceRemoveControl',true,'editor_slide');
						tinymce.execCommand('mceAddControl',true,'editor_slide');
				  },
				  open: function() {
						// Clear the editor
						tinymce.get('editor_slide').setContent('');
						// Hack for getting the reveal class added to tinymce editor body
						var $editorIframe = $('#editor_slide_ifr').contents();
						$editorIframe.find('body').addClass('reveal');
				  },
				  close: function() {
						self.closeModal();
				  }
				});
			});
		},

		// Adds a column to the presentation
		addColumn: function () {
			var self = this;
			var col = $('#container > .column').size() + 1;

			$('#container').append( '

'+col+'

' );
			$('#container').width( $('#container').width() + 210 );

			// Make sure all is good in the world
			//self.uiSetup();

			// Send this change off to ajax land
			//self.updatePresentation();
		},

		//Bind Add Column button to addColumn()
		bindButtonAddColumn: function () {
			var self = this;
			$('.action-buttons').on('click', '#add-column', function(e) {
				e.preventDefault();
				self.addColumn();
			});
		},

		//Bind View Presentation button
		bindButtonViewPresentation: function () {
			var self = this;
			$('.action-buttons').on('click', '#view-button', function(e) {
				e.preventDefault();
				window.open(WPPTaxonomyURL,'_blank');
			});
		},

		renumberColumns: function() {
			var i = 1;
			$( '.column' ).each(function( index ) {
				 var self = this;
				 var $self = $(this);
				 $self.find('> .widget-top > .widget-title > h4').html( i );
				i++;
			});
		}

	};

})(jQuery);
var slideManager = new WPPresentAdmin();<|endoftext|>


<commit_before>'use strict';

angular.module('repicbro.services')
  .factory('PostsManager', function ($rootScope, Posts) {

    var posts = [],
        current = null,
        index = 0,
        latest = "",
        updating = false;

    var broadcastCurrentUpdate = function (current) {
        $rootScope.$broadcast('PostsManager.CurrentUpdate', current);
    };

    var next = function () {
      console.log('next');
      checkSize();
      current = posts[++index];
      broadcastCurrentUpdate(current);
    };

    var prev = function () {
      console.log('prev');
      current = posts[--index];
      broadcastCurrentUpdate(current);
    };

    var checkSize = function () {
      if (posts.length - index < 50 && !updating) {
        getPosts();
      }
    };

    var getPosts = function () {
      console.log('Get posts');
      updating = true;
      Posts.get('funny', latest, function (data) {
        latest = data.data.name;

        angular.forEach(data.data.children, function (p) {
          posts.push(p.data);
        });
        current = posts[index];
        updating = false;
        broadcastCurrentUpdate(current);
      });
    };

    getPosts();

    return {
      posts: posts,
      current: current,
      next: next,
      prev: prev
    };
  });<commit_msg>JSHint<commit_after>'use strict';

angular.module('repicbro.services')
  .factory('PostsManager', function ($rootScope, Posts) {

    var posts = [],
        current = null,
        index = 0,
        latest = '',
        updating = false;

    var broadcastCurrentUpdate = function (current) {
      $rootScope.$broadcast('PostsManager.CurrentUpdate', current);
    };

    var next = function () {
      console.log('next');
      checkSize();
      current = posts[++index];
      broadcastCurrentUpdate(current);
    };

    var prev = function () {
      console.log('prev');
      current = posts[--index];
      broadcastCurrentUpdate(current);
    };

    var checkSize = function () {
      if (posts.length - index < 50 && !updating) {
        getPosts();
      }
    };

    var getPosts = function () {
      console.log('Get posts');
      updating = true;
      Posts.get('funny', latest, function (data) {
        latest = data.data.name;

        angular.forEach(data.data.children, function (p) {
          posts.push(p.data);
        });
        current = posts[index];
        updating = false;
        broadcastCurrentUpdate(current);
      });
    };

    getPosts();

    return {
      posts: posts,
      current: current,
      next: next,
      prev: prev
    };
  });<|endoftext|>


<commit_before>// helper functions
function randomInt(n) {
    return Math.floor(Math.random() * n);
};

function AgentBrain(gameEngine) {
    this.size = 4;
    this.previousState = gameEngine.grid.serialize();
    this.reset();
    this.score = 0;
};

AgentBrain.prototype.reset = function () {
    this.score = 0;
    this.grid = new Grid(this.previousState.size, this.previousState.cells);
};

// Adds a tile in a random position
AgentBrain.prototype.addRandomTile = function () {
    if (this.grid.cellsAvailable()) {
        var value = Math.random() < 0.9 ? 2 : 4;
        var tile = new Tile(this.grid.randomAvailableCell(), value);

        this.grid.insertTile(tile);
    }
};

AgentBrain.prototype.moveTile = function (tile, cell) {
    this.grid.cells[tile.x][tile.y] = null;
    this.grid.cells[cell.x][cell.y] = tile;
    tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
AgentBrain.prototype.move = function (direction) {
    // 0: up, 1: right, 2: down, 3: left
    var self = this;

    var cell, tile;

    var vector = this.getVector(direction);
    var traversals = this.buildTraversals(vector);
    var moved = false;

    //console.log(vector);

    //console.log(traversals);

    // Traverse the grid in the right direction and move tiles
    traversals.x.forEach(function (x) {
        traversals.y.forEach(function (y) {
            cell = {x: x, y: y};
            tile = self.grid.cellContent(cell);

            if (tile) {
                var positions = self.findFarthestPosition(cell, vector);
                var next = self.grid.cellContent(positions.next);

                // Only one merger per row traversal?
                if (next && next.value === tile.value && !next.mergedFrom) {
                    var merged = new Tile(positions.next, tile.value * 2);
                    merged.mergedFrom = [tile, next];

                    self.grid.insertTile(merged);
                    self.grid.removeTile(tile);

                    // Converge the two tiles' positions
                    tile.updatePosition(positions.next);

                    // Update the score
                    self.score += merged.value;

                } else {
                    self.moveTile(tile, positions.farthest);
                }

                if (!self.positionsEqual(cell, tile)) {
                    moved = true; // The tile moved from its original cell!
                }
            }
        });
    });
    //console.log(moved);
    if (moved) {
        this.addRandomTile();
    }
    return moved;
};

// Get the vector representing the chosen direction
AgentBrain.prototype.getVector = function (direction) {
    // Vectors representing tile movement
    var map = {
        0: {x: 0, y: -1}, // Up
        1: {x: 1, y: 0},  // Right
        2: {x: 0, y: 1},  // Down
        3: {x: -1, y: 0}   // Left
    };

    return map[direction];
};

// Build a list of positions to traverse in the right order
AgentBrain.prototype.buildTraversals = function (vector) {
    var traversals = {x: [], y: []};

    for (var pos = 0; pos < this.size; pos++) {
        traversals.x.push(pos);
        traversals.y.push(pos);
    }

    // Always traverse from the farthest cell in the chosen direction
    if (vector.x === 1) traversals.x = traversals.x.reverse();
    if (vector.y === 1) traversals.y = traversals.y.reverse();

    return traversals;
};

AgentBrain.prototype.findFarthestPosition = function (cell, vector) {
    var previous;

    // Progress towards the vector direction until an obstacle is found
    do {
        previous = cell;
        cell = {x: previous.x + vector.x, y: previous.y + vector.y};
    } while (this.grid.withinBounds(cell) &&
    this.grid.cellAvailable(cell));

    return {
        farthest: previous,
        next: cell // Used to check if a merge is required
    };
};

AgentBrain.prototype.positionsEqual = function (first, second) {
    return first.x === second.x && first.y === second.y;
};

function Agent() {
};

Agent.prototype.selectMove = function (gameManager) {
    var brain = new AgentBrain(gameManager);
    brain.reset();
    // Use the brain to simulate moves
    // i = 0: up, 1: right, 2: down, 3: left
    return this.evaluateGrid(gameManager);
};

Agent.prototype.evalHelper = function (i, gameManager) {
    var brain = new AgentBrain(gameManager);
    //brain.reset();
    var score = 0;
    var runs = 150;
    while (runs--) {
        if (!brain.move(i)) return 0;
        score += brain.score;
        for(var moves = 0; moves < 10; moves++){
            brain.move(randomInt(3));
            score += brain.score;
        }
        brain.reset();
    }
    return score;
};

Agent.prototype.evaluateGrid = function (gameManager) {
    // calculate a score for he current grid configuration
    var brain = new AgentBrain(gameManager);
    var aggregateScores = [0, 0, 0, 0];
    for (var i = 0; i < 4; i++) {
        aggregateScores[i] = this.evalHelper(i, gameManager);
    }
    var theMax = Math.max(aggregateScores[0], aggregateScores[1], aggregateScores[2], aggregateScores[3]);
    var nextBestMove = [aggregateScores[0], aggregateScores[1], aggregateScores[2], aggregateScores[3]];

    // sorts the aggregated scores in best order, instead of moving randomly
    // if the best move cannot be a legit move.
    nextBestMove.sort();

    // gets move by finding the index
    var theMove = aggregateScores.indexOf(theMax);

    if (brain.move(theMove)) {
        return theMove;
    } else if (brain.move(aggregateScores.indexOf(nextBestMove[1]))) {
        return aggregateScores.indexOf(nextBestMove[1]);
    } else if (brain.move(aggregateScores.indexOf(nextBestMove[2]))) {
        return aggregateScores.indexOf(nextBestMove[2]);
    } else {
        return aggregateScores.indexOf(nextBestMove[3]);
    }
};
<commit_msg>32k high score<commit_after>// helper functions
function randomInt(n) {
    return Math.floor(Math.random() * n);
};

function AgentBrain(gameEngine) {
    this.size = 4;
    this.previousState = gameEngine.grid.serialize();
    this.reset();
    this.score = 0;
};

AgentBrain.prototype.reset = function () {
    this.score = 0;
    this.grid = new Grid(this.previousState.size, this.previousState.cells);
};

// Adds a tile in a random position
AgentBrain.prototype.addRandomTile = function () {
    if (this.grid.cellsAvailable()) {
        var value = Math.random() < 0.9 ? 2 : 4;
        var tile = new Tile(this.grid.randomAvailableCell(), value);

        this.grid.insertTile(tile);
    }
};

AgentBrain.prototype.moveTile = function (tile, cell) {
    this.grid.cells[tile.x][tile.y] = null;
    this.grid.cells[cell.x][cell.y] = tile;
    tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
AgentBrain.prototype.move = function (direction) {
    // 0: up, 1: right, 2: down, 3: left
    var self = this;

    var cell, tile;

    var vector = this.getVector(direction);
    var traversals = this.buildTraversals(vector);
    var moved = false;

    //console.log(vector);

    //console.log(traversals);

    // Traverse the grid in the right direction and move tiles
    traversals.x.forEach(function (x) {
        traversals.y.forEach(function (y) {
            cell = {x: x, y: y};
            tile = self.grid.cellContent(cell);

            if (tile) {
                var positions = self.findFarthestPosition(cell, vector);
                var next = self.grid.cellContent(positions.next);

                // Only one merger per row traversal?
                if (next && next.value === tile.value && !next.mergedFrom) {
                    var merged = new Tile(positions.next, tile.value * 2);
                    merged.mergedFrom = [tile, next];

                    self.grid.insertTile(merged);
                    self.grid.removeTile(tile);

                    // Converge the two tiles' positions
                    tile.updatePosition(positions.next);

                    // Update the score
                    self.score += merged.value;

                } else {
                    self.moveTile(tile, positions.farthest);
                }

                if (!self.positionsEqual(cell, tile)) {
                    moved = true; // The tile moved from its original cell!
                }
            }
        });
    });
    //console.log(moved);
    if (moved) {
        this.addRandomTile();
    }
    return moved;
};

// Get the vector representing the chosen direction
AgentBrain.prototype.getVector = function (direction) {
    // Vectors representing tile movement
    var map = {
        0: {x: 0, y: -1}, // Up
        1: {x: 1, y: 0},  // Right
        2: {x: 0, y: 1},  // Down
        3: {x: -1, y: 0}   // Left
    };

    return map[direction];
};

// Build a list of positions to traverse in the right order
AgentBrain.prototype.buildTraversals = function (vector) {
    var traversals = {x: [], y: []};

    for (var pos = 0; pos < this.size; pos++) {
        traversals.x.push(pos);
        traversals.y.push(pos);
    }

    // Always traverse from the farthest cell in the chosen direction
    if (vector.x === 1) traversals.x = traversals.x.reverse();
    if (vector.y === 1) traversals.y = traversals.y.reverse();

    return traversals;
};

AgentBrain.prototype.findFarthestPosition = function (cell, vector) {
    var previous;

    // Progress towards the vector direction until an obstacle is found
    do {
        previous = cell;
        cell = {x: previous.x + vector.x, y: previous.y + vector.y};
    } while (this.grid.withinBounds(cell) &&
    this.grid.cellAvailable(cell));

    return {
        farthest: previous,
        next: cell // Used to check if a merge is required
    };
};

AgentBrain.prototype.positionsEqual = function (first, second) {
    return first.x === second.x && first.y === second.y;
};

function Agent() {
};

Agent.prototype.selectMove = function (gameManager) {
    var brain = new AgentBrain(gameManager);
    brain.reset();
    // Use the brain to simulate moves
    // i = 0: up, 1: right, 2: down, 3: left
    return this.evaluateGrid(gameManager);
};

Agent.prototype.evalHelper = function (i, gameManager) {
    var brain = new AgentBrain(gameManager);
    //brain.reset();
    var score = 0;
    var runs = 50;
    while (runs--) {
        if (!brain.move(i)) return 0;
        //score += brain.score;
        for (var moves = 0; moves < 20; moves++) {
            brain.move(randomInt(3));
            //score += brain.score;
        }
        score += brain.score;
        brain.reset();
    }
    return score;
};

Agent.prototype.evaluateGrid = function (gameManager) {
    // calculate a score for he current grid configuration
    var brain = new AgentBrain(gameManager);
    var aggregateScores = [0, 0, 0, 0];
    for (var i = 0; i < 4; i++) {
        aggregateScores[i] = this.evalHelper(i, gameManager);
    }
    var theMax = Math.max(aggregateScores[0], aggregateScores[1], aggregateScores[2], aggregateScores[3]);
    var nextBestMove = [aggregateScores[0], aggregateScores[1], aggregateScores[2], aggregateScores[3]];

    // sorts the aggregated scores in best order, instead of moving randomly
    // if the best move cannot be a legit move.
    nextBestMove.sort();

    // gets move by finding the index
    var theMove = aggregateScores.indexOf(theMax);

    if (brain.move(theMove)) {
        return theMove;
    } else if (brain.move(aggregateScores.indexOf(nextBestMove[1]))) {
        return aggregateScores.indexOf(nextBestMove[1]);
    } else if (brain.move(aggregateScores.indexOf(nextBestMove[2]))) {
        return aggregateScores.indexOf(nextBestMove[2]);
    } else {
        return aggregateScores.indexOf(nextBestMove[3]);
    }
};
<|endoftext|>


<commit_before>let lab = [];
let anc = [];
let w = 1; // box width
let h = 1; // box width

const maxMove = 25.0;
const maxAngle = 0.5;
let acc = 0;
let rej = 0;

// weights
const wLen = 5.0; // leader line length
const wInter = 50.0; // leader line intersection
const wLabLab = 50.0; // label-label overlap
const wLabOrg = 50.0; // additional label-origin overlap weights (added to `wLabAnc`)
const wLabAnc = 10.0; // overlap between label and other anchors (i.e., annotations)
const wOrient = 0.1; // orientation bias

// booleans for user defined functions
let userEnergy = false;
let userSchedule = false;

let userDefinedEnergy;
let userDefinedSchedule;

// returns true if two lines intersect, else false
// from http://paulbourke.net/geometry/lineline2d/
const intersect = (x1, x2, x3, x4, y1, y2, y3, y4) => {
  const denom = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1));
  const numera = ((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3));
  const numerb = ((x2 - x1) * (y1 - y3)) - ((y2 - y1) * (x1 - x3));

  /* Is the intersection along the the segments */
  const mua = numera / denom;
  const mub = numerb / denom;

  return (!(mua < 0 || mua > 1 || mub < 0 || mub > 1));
};

// energy function, tailored for label placement
const energy = (index) => {
  const m = lab.length;
  const n = anc.length;
  const l = lab[index];
  let ener = 0;
  const dx = l.x - l.ox;
  const dy = l.y - l.oy;
  const dist = Math.sqrt((dx * dx) + (dy * dy));
  const distCenterToBorder = Math.sqrt((l.wh * l.wh) + (l.hh * l.hh));
  let overlap = true;
  // let amount = 0;
  // let theta = 0;

  // penalty for length of leader line
  ener += Math.abs(dist - distCenterToBorder) * wLen;

  // label orientation bias (Fritz: ignored for now)
  // dx /= dist;
  // dy /= dist;
  // if (dx > 0 && dy > 0) ener += 0 * wOrient;
  // else if (dx < 0 && dy > 0) ener += 1 * wOrient;
  // else if (dx < 0 && dy < 0) ener += 2 * wOrient;
  // else ener += 3 * wOrient;

  const x21 = l.x - l.wh - 1;
  const y21 = l.y - l.hh - 1;
  const x22 = l.x + l.wh + 1;
  const y22 = l.y + l.hh + 1;
  let x11;
  let x12;
  let y11;
  let y12;
  let xOverlap;
  let yOverlap;
  let overlapArea;

  // For every annotation
  // Note: we know that the first m anchors are the label origins
  for (let i = 0; i < n; i++) {
    // For every other label (m = number of labels)
    if (i !== index && i < m) {
      const otherLabel = lab[i];
      // Test if leader lines intersect...
      overlap = intersect(
        anc[index].x,
        l.x,
        anc[i].x,
        otherLabel.x,
        anc[index].y,
        l.y,
        anc[i].y,
        otherLabel.y
      );

      // ...and add a penalty if they do
      if (overlap) ener += wInter;

      // Penalty for label-label overlap
      x11 = otherLabel.x - otherLabel.wh - 1;
      y11 = otherLabel.y - otherLabel.hh - 1;
      x12 = otherLabel.x + otherLabel.wh + 1;
      y12 = otherLabel.y + otherLabel.hh + 1;
      xOverlap = Math.max(0, Math.min(x12, x22) - Math.max(x11, x21));
      yOverlap = Math.max(0, Math.min(y12, y22) - Math.max(y11, y21));
      overlapArea = xOverlap * yOverlap;
      ener += (overlapArea * wLabLab);
    }

    // penalty for label-anchor overlap
    x11 = anc[i].x - anc[i].wh - 1;
    y11 = anc[i].y - anc[i].hh - 1;
    x12 = anc[i].x + anc[i].wh + 1;
    y12 = anc[i].y + anc[i].hh + 1;
    xOverlap = Math.max(0, Math.min(x12, x22) - Math.max(x11, x21));
    yOverlap = Math.max(0, Math.min(y12, y22) - Math.max(y11, y21));
    overlapArea = xOverlap * yOverlap;
    ener += overlapArea * (wLabAnc + (wLabOrg * (i < m)));
  }
  return ener;
};

// Monte Carlo translation move
const mcmove = (currT) => {
  // select a random label
  const i = Math.floor(Math.random() * lab.length);
  const l = lab[i];

  // save old coordinates
  const xOld = l.x;
  const yOld = l.y;

  // old energy
  const oldEnergy = userEnergy
    ? userDefinedEnergy(i, lab, anc)
    : energy(i);

  // random translation
  l.x += (Math.random() - 0.5) * maxMove * Math.max(0.5, currT);
  l.y += (Math.random() - 0.5) * maxMove * Math.max(0.5, currT);

  // hard wall boundaries
  // if (l.x > w) l.x = xOld;
  // if (l.x < 0) l.x = xOld;
  // if (l.y > h) l.y = yOld;
  // if (l.y < 0) l.y = yOld;

  // new energy
  const newEnergy = userEnergy
    ? userDefinedEnergy(i, lab, anc)
    : energy(i);

  // delta E
  const deltaEnergy = newEnergy - oldEnergy;

  if (Math.random() < Math.exp(-deltaEnergy / currT)) {
    acc += 1;
  } else {
    // move back to old coordinates
    l.x = xOld;
    l.y = yOld;
    rej += 1;
  }
};

// Monte Carlo rotation move
const mcrotate = (currT) => {
  // select a random label
  const i = Math.floor(Math.random() * lab.length);

  // save old coordinates
  const xOld = lab[i].x;
  const yOld = lab[i].y;

  // old energy
  const oldEnergy = userEnergy
    ? userDefinedEnergy(i, lab, anc)
    : energy(i);

  // random angle
  const angle = (Math.random() - 0.5) * maxAngle;

  const s = Math.sin(angle);
  const c = Math.cos(angle);

  // translate label (relative to anchor at origin):
  lab[i].x -= anc[i].x;
  lab[i].y -= anc[i].y;

  // rotate label
  const xNew = (lab[i].x * c) - (lab[i].y * s);
  const yNew = (lab[i].x * s) + (lab[i].y * c);

  // translate label back
  lab[i].x = xNew + anc[i].x;
  lab[i].y = yNew + anc[i].y;

  // hard wall boundaries
  if (lab[i].x > w) lab[i].x = xOld;
  if (lab[i].x < 0) lab[i].x = xOld;
  if (lab[i].y > h) lab[i].y = yOld;
  if (lab[i].y < 0) lab[i].y = yOld;

  // new energy
  const newEnergy = userEnergy
    ? userDefinedEnergy(i, lab, anc)
    : energy(i);

  // delta E
  const deltaEnergy = newEnergy - oldEnergy;

  if (Math.random() < Math.exp(-deltaEnergy / currT)) {
    acc += 1;
  } else {
    // move back to old coordinates
    lab[i].x = xOld;
    lab[i].y = yOld;
    rej += 1;
  }
};

// linear cooling
const coolingSchedule = (currT, initialT, nsweeps) => (currT - (initialT / nsweeps));

const labeler = {};

// main simulated annealing function
labeler.start = (nsweeps, t = 1.0) => {
  const m = lab.length;
  const initialT = t;
  let currT = initialT;

  for (let i = 0; i < nsweeps; i++) {
    for (let j = 0; j < m; j++) {
      mcmove(currT);
      // Fritz: ignoring rotations for now
      // if (Math.random() < 0.5) mcmove(currT);
      // else mcrotate(currT);
    }
    currT = coolingSchedule(currT, initialT, nsweeps);
  }
};

labeler.width = (x) => {
// users insert graph width
  if (!arguments.length) return w;
  w = x;
  return labeler;
};

labeler.height = (x) => {
// users insert graph height
  if (!arguments.length) return h;
  h = x;
  return labeler;
};

// users insert label positions
labeler.label = (x) => {
  if (!arguments.length) return lab;
  lab = x;
  return labeler;
};

// users insert anchor positions
labeler.anchor = (x) => {
  if (!arguments.length) return anc;
  anc = x;
  return labeler;
};

labeler.altEnergy = (x) => {
// user defined energy
  if (!arguments.length) return energy;
  userDefinedEnergy = x;
  userEnergy = true;
  return labeler;
};

labeler.altSchedule = (x) => {
// user defined coolingSchedule
  if (!arguments.length) return coolingSchedule;
  userDefinedSchedule = x;
  userSchedule = true;
  return labeler;
};

export default labeler;
<commit_msg>Add option to restrict annealing to 1 dimension<commit_after>let lab = [];
let anc = [];
let w = 1; // box width
let h = 1; // box width

const maxMove = 25.0;
const maxAngle = 0.5;
let acc = 0;
let rej = 0;

// weights
const wLen = 5.0; // leader line length
const wInter = 50.0; // leader line intersection
const wLabLab = 50.0; // label-label overlap
const wLabOrg = 50.0; // additional label-origin overlap weights (added to `wLabAnc`)
const wLabAnc = 10.0; // overlap between label and other anchors (i.e., annotations)
const wOrient = 0.1; // orientation bias

// booleans for user defined functions
let userEnergy = false;
let userSchedule = false;

let userDefinedEnergy;
let userDefinedSchedule;

let is1dOnly = false;

// returns true if two lines intersect, else false
// from http://paulbourke.net/geometry/lineline2d/
const intersect = (x1, x2, x3, x4, y1, y2, y3, y4) => {
  const denom = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1));
  const numera = ((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3));
  const numerb = ((x2 - x1) * (y1 - y3)) - ((y2 - y1) * (x1 - x3));

  /* Is the intersection along the the segments */
  const mua = numera / denom;
  const mub = numerb / denom;

  return (!(mua < 0 || mua > 1 || mub < 0 || mub > 1));
};

// energy function, tailored for label placement
const energy = (index) => {
  const m = lab.length;
  const n = anc.length;
  const mn = Math.max(m, n);
  const l = lab[index];
  let ener = 0;
  const dx = l.x - l.ox;
  const dy = l.y - l.oy;
  const dist = Math.sqrt((dx * dx) + (dy * dy));
  const distCenterToBorder = Math.sqrt((l.wh * l.wh) + (l.hh * l.hh));
  let overlap = true;
  // let amount = 0;
  // let theta = 0;

  // penalty for length of leader line
  ener += Math.abs(dist - distCenterToBorder) * wLen;

  // label orientation bias (Fritz: ignored for now)
  // dx /= dist;
  // dy /= dist;
  // if (dx > 0 && dy > 0) ener += 0 * wOrient;
  // else if (dx < 0 && dy > 0) ener += 1 * wOrient;
  // else if (dx < 0 && dy < 0) ener += 2 * wOrient;
  // else ener += 3 * wOrient;

  const x21 = l.x - l.wh - 1;
  const y21 = l.y - l.hh - 1;
  const x22 = l.x + l.wh + 1;
  const y22 = l.y + l.hh + 1;
  let x11;
  let x12;
  let y11;
  let y12;
  let xOverlap;
  let yOverlap;
  let overlapArea;

  // For every annotation or label
  // Note: we know that the first m anchors are the label origins
  for (let i = 0; i < mn; i++) {
    // For every other label (m = number of labels)
    if (i !== index && i < m) {
      const otherLabel = lab[i];
      // Test if leader lines intersect...
      overlap = intersect(
        anc[index].x,
        l.x,
        anc[i].x,
        otherLabel.x,
        anc[index].y,
        l.y,
        anc[i].y,
        otherLabel.y
      );

      // ...and add a penalty if they do
      if (overlap) ener += wInter;

      // Penalty for label-label overlap
      x11 = otherLabel.x - otherLabel.wh - 1;
      y11 = otherLabel.y - otherLabel.hh - 1;
      x12 = otherLabel.x + otherLabel.wh + 1;
      y12 = otherLabel.y + otherLabel.hh + 1;
      xOverlap = Math.max(0, Math.min(x12, x22) - Math.max(x11, x21));
      yOverlap = Math.max(0, Math.min(y12, y22) - Math.max(y11, y21));
      overlapArea = xOverlap * yOverlap;
      ener += (overlapArea * wLabLab);
    }

    // penalty for label-anchor overlap
    x11 = anc[i].x - anc[i].wh - 1;
    y11 = anc[i].y - anc[i].hh - 1;
    x12 = anc[i].x + anc[i].wh + 1;
    y12 = anc[i].y + anc[i].hh + 1;
    xOverlap = Math.max(0, Math.min(x12, x22) - Math.max(x11, x21));
    yOverlap = Math.max(0, Math.min(y12, y22) - Math.max(y11, y21));
    overlapArea = xOverlap * yOverlap;
    ener += overlapArea * (wLabAnc + (wLabOrg * (i < m)));
  }
  return ener;
};

// Monte Carlo translation move
const mcmove = (currT) => {
  // select a random label
  const i = Math.floor(Math.random() * lab.length);
  const l = lab[i];

  // save old coordinates
  const xOld = l.x;
  const yOld = l.y;

  // old energy
  const oldEnergy = userEnergy
    ? userDefinedEnergy(i, lab, anc)
    : energy(i);

  const getRndMove = () => (Math.random() - 0.5) * maxMove * Math.max(0.5, currT);

  // random translation
  const moveX = +(((is1dOnly * !l.isVerticalOnly) + !is1dOnly) && getRndMove());
  const moveY = +(((is1dOnly * l.isVerticalOnly) + !is1dOnly) && getRndMove());
  l.x += moveX;
  l.y += moveY;

  // hard wall boundaries
  // if (l.x > w) l.x = xOld;
  // if (l.x < 0) l.x = xOld;
  // if (l.y > h) l.y = yOld;
  // if (l.y < 0) l.y = yOld;

  // new energy
  const newEnergy = userEnergy
    ? userDefinedEnergy(i, lab, anc)
    : energy(i);

  // delta E
  const deltaEnergy = newEnergy - oldEnergy;

  if (Math.random() < Math.exp(-deltaEnergy / currT)) {
    acc += 1;
  } else {
    // move back to old coordinates
    l.x = xOld;
    l.y = yOld;
    rej += 1;
  }
};

// Monte Carlo rotation move
const mcrotate = (currT) => {
  // select a random label
  const i = Math.floor(Math.random() * lab.length);

  // save old coordinates
  const xOld = lab[i].x;
  const yOld = lab[i].y;

  // old energy
  const oldEnergy = userEnergy
    ? userDefinedEnergy(i, lab, anc)
    : energy(i);

  // random angle
  const angle = (Math.random() - 0.5) * maxAngle;

  const s = Math.sin(angle);
  const c = Math.cos(angle);

  // translate label (relative to anchor at origin):
  lab[i].x -= anc[i].x;
  lab[i].y -= anc[i].y;

  // rotate label
  const xNew = (lab[i].x * c) - (lab[i].y * s);
  const yNew = (lab[i].x * s) + (lab[i].y * c);

  // translate label back
  lab[i].x = xNew + anc[i].x;
  lab[i].y = yNew + anc[i].y;

  // hard wall boundaries
  if (lab[i].x > w) lab[i].x = xOld;
  if (lab[i].x < 0) lab[i].x = xOld;
  if (lab[i].y > h) lab[i].y = yOld;
  if (lab[i].y < 0) lab[i].y = yOld;

  // new energy
  const newEnergy = userEnergy
    ? userDefinedEnergy(i, lab, anc)
    : energy(i);

  // delta E
  const deltaEnergy = newEnergy - oldEnergy;

  if (Math.random() < Math.exp(-deltaEnergy / currT)) {
    acc += 1;
  } else {
    // move back to old coordinates
    lab[i].x = xOld;
    lab[i].y = yOld;
    rej += 1;
  }
};

// linear cooling
const coolingSchedule = (currT, initialT, nsweeps) => (currT - (initialT / nsweeps));

const labeler = {};

// main simulated annealing function
labeler.start = (nsweeps, t = 1.0) => {
  const m = lab.length;
  const initialT = t;
  let currT = initialT;

  for (let i = 0; i < nsweeps; i++) {
    for (let j = 0; j < m; j++) {
      mcmove(currT);
      // Fritz: ignoring rotations for now
      // if (Math.random() < 0.5) mcmove(currT);
      // else mcrotate(currT);
    }
    currT = coolingSchedule(currT, initialT, nsweeps);
  }
};

labeler.width = (x) => {
// users insert graph width
  if (!arguments.length) return w;
  w = x;
  return labeler;
};

labeler.height = (x) => {
// users insert graph height
  if (!arguments.length) return h;
  h = x;
  return labeler;
};

// users insert label positions
labeler.label = (x) => {
  if (!arguments.length) return lab;
  lab = x;
  return labeler;
};

// users insert anchor positions
labeler.anchor = (x) => {
  if (!arguments.length) return anc;
  anc = x;
  return labeler;
};

labeler.altEnergy = (x) => {
// user defined energy
  if (!arguments.length) return energy;
  userDefinedEnergy = x;
  userEnergy = true;
  return labeler;
};

labeler.altSchedule = (x) => {
// user defined coolingSchedule
  if (!arguments.length) return coolingSchedule;
  userDefinedSchedule = x;
  userSchedule = true;
  return labeler;
};

/**
 * Restrict annealing to be one dimensional if `isFalse` is `false`.
 * @param   {boolean}  isFalse  If `true` deactivate one-dimensional annealing.
 * @return  {object}  Return the labeler for chaining.
 */
labeler.is1dOnly = (isFalse = false) => {
  if (!arguments.length) return is1dOnly;
  is1dOnly = !isFalse;
  return labeler;
};

export default labeler;
<|endoftext|>


<commit_before>'use strict';
const imm = require('immutable'),
	util = require('../util'),
	statuscache = {},
	activecache = {},
	activecastcache = {};
function Card(type, info) {
	this.type = type;
	this.element = info.E;
	this.name = info.Name;
	this.code = info.Code;
	this.tier = info.Tier;
	this.attack = info.Attack || 0;
	this.health = info.Health || 0;
	if (info.Cost) {
		[this.cost, this.costele] = readCost(info.Cost, this.element);
	} else {
		this.cost = 0;
		this.costele = 0;
	}
	if (info.Active) {
		if (this.type === etg.SpellEnum) {
			this.active = new imm.Map({ cast: Actives[info.Active] });
			this.cast = this.cost;
			this.castele = this.costele;
		} else if (info.Active in activecache) {
			this.active = activecache[info.Active];
			const castinfo = activecastcache[info.Active];
			if (castinfo) {
				[this.cast, this.castele] = castinfo;
			}
		} else {
			this.active = new imm.Map();
			for (const active of util.iterSplit(info.Active, '+')) {
				const eqidx = active.indexOf('=');
				const a0 = ~eqidx ? active.substr(0, eqidx) : 'auto';
				const cast = readCost(a0, this.element);
				Thing.prototype.addactive.call(
					this,
					cast ? 'cast' : a0,
					Actives[active.substr(eqidx + 1)],
				);
				if (cast) {
					[this.cast, this.castele] = cast;
					activecastcache[info.Skill] = cast;
				}
			}
			activecache[info.Active] = this.active;
		}
	} else this.active = new imm.Map();
	if (info.Status) {
		if (info.Status in statuscache) {
			this.status = statuscache[info.Status];
		} else {
			this.status = new imm.Map();
			for (const status of util.iterSplit(info.Status, '+')) {
				const eqidx = status.indexOf('=');
				this.status = this.status.set(
					~eqidx ? status.substr(0, eqidx) : status,
					eqidx == -1 || +status.substr(eqidx + 1),
				);
			}
			statuscache[info.Status] = this.status;
		}
	} else this.status = new imm.Map();
}
Object.defineProperty(Card.prototype, 'upped', {
	get: function() {
		return (this.code & 0x3fff) > 6999;
	},
});
module.exports = Card;
Card.prototype.info = function() {
	if (this.type == etg.SpellEnum) {
		return skillText(this);
	} else {
		var text = [];
		if (this.type == etg.ShieldEnum && this.health)
			text.push('Reduce damage by ' + this.health);
		else if (this.type == etg.CreatureEnum || this.type == etg.WeaponEnum)
			text.push(this.attack + '|' + this.health);
		var skills = skillText(this);
		if (skills) text.push(skills);
		return text.join('\n');
	}
};
Card.prototype.toString = function() {
	return this.code;
};
Card.prototype.asUpped = function(upped) {
	return this.upped == upped
		? this
		: Cards.Codes[etgutil.asUpped(this.code, upped)];
};
Card.prototype.isOf = function(card) {
	return card.code == etgutil.asUpped(this.code, false);
};
Card.prototype.getStatus = function(key) {
	return this.status.get(key) || 0;
}
function readCost(coststr, defaultElement) {
	if (typeof coststr == 'number')
		return new Int8Array([coststr, defaultElement]);
	const cidx = coststr.indexOf(':'),
		cost = +(~cidx ? coststr.substr(0, cidx) : coststr);
	return isNaN(cost)
		? null
		: new Int8Array([
				cost,
				~cidx ? +(coststr.substr(cidx + 1)) : defaultElement,
			]);
}

var etg = require('./etg');
var {Thing} = require('./Thing');
var Cards = require('./Cards');
var etgutil = require('../etgutil');
var skillText = require('./skillText');
var Actives = require('./Skills');
<commit_msg>This should fix upped actives<commit_after>'use strict';
const imm = require('immutable'),
	util = require('../util'),
	statuscache = {},
	activecache = {},
	activecastcache = {};
function Card(type, info) {
	this.type = type;
	this.element = info.E;
	this.name = info.Name;
	this.code = info.Code;
	this.tier = info.Tier;
	this.attack = info.Attack || 0;
	this.health = info.Health || 0;
	if (info.Cost) {
		[this.cost, this.costele] = readCost(info.Cost, this.element);
	} else {
		this.cost = 0;
		this.costele = 0;
	}
	if (info.Active) {
		if (this.type === etg.Spell) {
			this.active = new imm.Map({ cast: Actives[info.Active] });
			this.cast = this.cost;
			this.castele = this.costele;
		} else if (info.Active in activecache) {
			this.active = activecache[info.Active];
			const castinfo = activecastcache[info.Active];
			if (castinfo) {
				[this.cast, this.castele] = castinfo;
			}
		} else {
			this.active = new imm.Map();
			for (const active of util.iterSplit(info.Active, '+')) {
				const eqidx = active.indexOf('=');
				const a0 = ~eqidx ? active.substr(0, eqidx) : 'auto';
				const cast = readCost(a0, this.element);
				Thing.prototype.addactive.call(
					this,
					cast ? 'cast' : a0,
					Actives[active.substr(eqidx + 1)],
				);
				if (cast) {
					[this.cast, this.castele] = cast;
					activecastcache[info.Active] = cast;
				}
			}
			activecache[info.Active] = this.active;
		}
	} else this.active = new imm.Map();
	if (info.Status) {
		if (info.Status in statuscache) {
			this.status = statuscache[info.Status];
		} else {
			this.status = new imm.Map();
			for (const status of util.iterSplit(info.Status, '+')) {
				const eqidx = status.indexOf('=');
				this.status = this.status.set(
					~eqidx ? status.substr(0, eqidx) : status,
					eqidx == -1 || +status.substr(eqidx + 1),
				);
			}
			statuscache[info.Status] = this.status;
		}
	} else this.status = new imm.Map();
}
Object.defineProperty(Card.prototype, 'upped', {
	get: function() {
		return (this.code & 0x3fff) > 6999;
	},
});
module.exports = Card;
Card.prototype.info = function() {
	if (this.type == etg.Spell) {
		return skillText(this);
	} else {
		var text = [];
		if (this.type == etg.Shield && this.health)
			text.push('Reduce damage by ' + this.health);
		else if (this.type == etg.Creature || this.type == etg.Weapon)
			text.push(this.attack + '|' + this.health);
		var skills = skillText(this);
		if (skills) text.push(skills);
		return text.join('\n');
	}
};
Card.prototype.toString = function() {
	return this.code;
};
Card.prototype.asUpped = function(upped) {
	return this.upped == upped
		? this
		: Cards.Codes[etgutil.asUpped(this.code, upped)];
};
Card.prototype.isOf = function(card) {
	return card.code == etgutil.asUpped(this.code, false);
};
Card.prototype.getStatus = function(key) {
	return this.status.get(key) || 0;
}
function readCost(coststr, defaultElement) {
	if (typeof coststr == 'number')
		return new Int8Array([coststr, defaultElement]);
	const cidx = coststr.indexOf(':'),
		cost = +(~cidx ? coststr.substr(0, cidx) : coststr);
	return isNaN(cost)
		? null
		: new Int8Array([
				cost,
				~cidx ? +(coststr.substr(cidx + 1)) : defaultElement,
			]);
}

var etg = require('./etg');
var {Thing} = require('./Thing');
var Cards = require('./Cards');
var etgutil = require('../etgutil');
var skillText = require('./skillText');
var Actives = require('./Skills');
<|endoftext|>


<commit_before>import { expect } from 'chai';

import bb, { bollingerBandsArray as bba } from '@binary-com/binary-indicators/lib/bollingerBands';
import rsi, { relativeStrengthIndexArray as rsia } from '@binary-com/binary-indicators/lib/relativeStrengthIndex';
import ema, { exponentialMovingAverageArray as emaa } from '@binary-com/binary-indicators/lib/exponentialMovingAverage';
import sma, { simpleMovingAverageArray as smaa } from '@binary-com/binary-indicators/lib/simpleMovingAverage';
// import macda from '@binary-com/binary-indicators/lib/macd';

import { runAndGetResult } from '../tools';

const periods = 12;

const bbOption = {
    periods,
    stdDevUp  : 5,
    stdDevDown: 5,
};

const macdOption = {
    fastEmaPeriod  : 12,
    slowEmaPeriod  : 26,
    signalEmaPeriod: 9,
};

const getIndicatorsFromApi = () =>
    runAndGetResult(
        undefined,
        `
    watch('before');
    var ticks = Bot.getTicks();
    result.ticks = ticks
    result.rsi = Bot.rsi(ticks, ${periods})
    result.rsia = Bot.rsia(ticks, ${periods})
    result.bb = Bot.bb(ticks, ${JSON.stringify(bbOption)}, 1)
    result.bba = Bot.bba(ticks, ${JSON.stringify(bbOption)}, 2)
    result.ema = Bot.ema(ticks, ${periods})
    result.emaa = Bot.emaa(ticks, ${periods})
    result.macda = Bot.macda(ticks, ${JSON.stringify(macdOption)}, 0)
    result.sma = Bot.sma(ticks, ${periods})
    result.smaa = Bot.smaa(ticks, ${periods})
  `
    );

describe('Relative Strength Index', () => {
    let result;
    let expected;

    beforeAll(done =>
        getIndicatorsFromApi().then(r => {
            result = r;
            const { ticks } = result;

            expected = {
                sma  : sma(ticks, { periods }),
                smaa : smaa(ticks, { periods }),
                bb   : bb(ticks, bbOption)[1],
                bba  : bba(ticks, bbOption).map(e => e[2]),
                ema  : ema(ticks, { periods }),
                emaa : emaa(ticks, { periods }),
                rsi  : rsi(ticks, { periods }),
                rsia : rsia(ticks, { periods }),
                macda: macda(ticks, macdOption).map(e => e[0]),
            };

            done();
        })
    );

    it('Indicator values are set correctly', () => {
        Object.keys(expected).forEach(name => {
            const endResult = JSON.parse(JSON.stringify(result[name]));
            const expectedResult = JSON.parse(JSON.stringify(expected[name]));
            expect(endResult).to.deep.equal(expectedResult);
        });
    });
});
<commit_msg>Uncomment macda import<commit_after>import { expect } from 'chai';

import bb, { bollingerBandsArray as bba } from '@binary-com/binary-indicators/lib/bollingerBands';
import rsi, { relativeStrengthIndexArray as rsia } from '@binary-com/binary-indicators/lib/relativeStrengthIndex';
import ema, { exponentialMovingAverageArray as emaa } from '@binary-com/binary-indicators/lib/exponentialMovingAverage';
import sma, { simpleMovingAverageArray as smaa } from '@binary-com/binary-indicators/lib/simpleMovingAverage';
import macda from '@binary-com/binary-indicators/lib/macd';

import { runAndGetResult } from '../tools';

const periods = 12;

const bbOption = {
    periods,
    stdDevUp  : 5,
    stdDevDown: 5,
};

const macdOption = {
    fastEmaPeriod  : 12,
    slowEmaPeriod  : 26,
    signalEmaPeriod: 9,
};

const getIndicatorsFromApi = () =>
    runAndGetResult(
        undefined,
        `
    watch('before');
    var ticks = Bot.getTicks();
    result.ticks = ticks
    result.rsi = Bot.rsi(ticks, ${periods})
    result.rsia = Bot.rsia(ticks, ${periods})
    result.bb = Bot.bb(ticks, ${JSON.stringify(bbOption)}, 1)
    result.bba = Bot.bba(ticks, ${JSON.stringify(bbOption)}, 2)
    result.ema = Bot.ema(ticks, ${periods})
    result.emaa = Bot.emaa(ticks, ${periods})
    result.macda = Bot.macda(ticks, ${JSON.stringify(macdOption)}, 0)
    result.sma = Bot.sma(ticks, ${periods})
    result.smaa = Bot.smaa(ticks, ${periods})
  `
    );

describe('Relative Strength Index', () => {
    let result;
    let expected;

    beforeAll(done =>
        getIndicatorsFromApi().then(r => {
            result = r;
            const { ticks } = result;

            expected = {
                sma  : sma(ticks, { periods }),
                smaa : smaa(ticks, { periods }),
                bb   : bb(ticks, bbOption)[1],
                bba  : bba(ticks, bbOption).map(e => e[2]),
                ema  : ema(ticks, { periods }),
                emaa : emaa(ticks, { periods }),
                rsi  : rsi(ticks, { periods }),
                rsia : rsia(ticks, { periods }),
                macda: macda(ticks, macdOption).map(e => e[0]),
            };

            done();
        })
    );

    it('Indicator values are set correctly', () => {
        Object.keys(expected).forEach(name => {
            const endResult = JSON.parse(JSON.stringify(result[name]));
            const expectedResult = JSON.parse(JSON.stringify(expected[name]));
            expect(endResult).to.deep.equal(expectedResult);
        });
    });
});
<|endoftext|>


<commit_before>dojo.provide("dojox.form.CheckedMultiSelect");

dojo.require("dijit.form.CheckBox");
dojo.require("dojox.form._FormSelectWidget");

dojo.declare("dojox.form._CheckedMultiSelectItem",
	[dijit._Widget, dijit._Templated],
	{
	// summary:
	//		The individual items for a CheckedMultiSelect

	widgetsInTemplate: true,
	templatePath: dojo.moduleUrl("dojox.form", "resources/_CheckedMultiSelectItem.html"),

	baseClass: "dojoxMultiSelectItem",

	// option: dojox.form.__SelectOption
	//		The option that is associated with this item
	option: null,
	parent: null,

	// disabled: boolean
	//		Whether or not this widget is disabled
	disabled: false,

	// readOnly: boolean
	//		Whether or not this widget is readOnly
	readOnly: false,

	postMixInProperties: function(){
		// summary:
		//		Set the appropriate _subClass value - based on if we are multi-
		//		or single-select
		if(this.parent._multiValue){
			this._type = {type: "checkbox", baseClass: "dijitCheckBox"};
		}else{
			this._type = {type: "radio", baseClass: "dijitRadio"};
		}
		this.inherited(arguments);
	},

	postCreate: function(){
		// summary:
		//		Set innerHTML here - since the template gets messed up sometimes
		//		with rich text
		this.inherited(arguments);
		this.labelNode.innerHTML = this.option.label;
	},

	_changeBox: function(){
		// summary:
		//		Called to force the select to match the state of the check box
		//		(only on click of the checkbox)  Radio-based calls _setValueAttr
		//		instead.
		if(this.attr("disabled") || this.attr("readOnly")){ return; }
		if(this.parent._multiValue){
			this.option.selected = this.checkBox.attr('value') && true;
		}else{
			this.parent.attr('value', this.option.value);
		}
		// fire the parent's change
		this.parent._updateSelection();

		// refocus the parent
		this.parent.focus();
	},

	_onMouse: function(e){
		// summary:
		//		Sets the hover state depending on mouse state (passes through
		//		to the check box)
		if(this.attr("disabled") || this.attr("readOnly")){
			dojo.stopEvent(e);
		}else{
			this.checkBox._onMouse(e);
		}
	},

	_onClick: function(e){
		// summary:
		//		Sets the click state (passes through to the check box)
		if(this.attr("disabled") || this.attr("readOnly")){
			dojo.stopEvent(e);
		}else{
			this.checkBox._onClick(e);
		}
	},

	_updateBox: function(){
		// summary:
		//		Called to force the box to match the state of the select
		this.checkBox.attr('value', this.option.selected);
	},

	_setDisabledAttr: function(value){
		// summary:
		//		Disables (or enables) all the children as well
		this.checkBox.attr("disabled", value);
		this.disabled = value;
	},

	_setReadOnlyAttr: function(value){
		// summary:
		//		Sets read only (or unsets) all the children as well
		this.checkBox.attr("readOnly", value);
		this.checkBox._setStateClass();
		this.readOnly = value;
	}
});

dojo.declare("dojox.form.CheckedMultiSelect", dojox.form._FormSelectWidget, {
	// summary:
	//		Extends the core dijit MultiSelect to provide a "checkbox" selector

	templateString: "",
	templatePath: dojo.moduleUrl("dojox.form", "resources/CheckedMultiSelect.html"),

	baseClass: "dojoxMultiSelect",

	_mouseDown: function(e){
		// summary:
		//		Cancels the mousedown event to prevent others from stealing
		//		focus
		dojo.stopEvent(e);
	},

	_addOptionItem: function(/* dojox.form.__SelectOption */ option){
		this.wrapperDiv.appendChild(new dojox.form._CheckedMultiSelectItem({
			option: option,
			parent: this
		}).domNode);
	},

	_updateSelection: function(){
		this.inherited(arguments);
		dojo.forEach(this._getChildren(), function(c){ c._updateBox(); });
	},

	_getChildren: function(){
		return dojo.map(this.wrapperDiv.childNodes, function(n){
			return dijit.byNode(n);
		});
	},

	invertSelection: function(onChange){
		// summary: Invert the selection
		// onChange: Boolean
		//		If null, onChange is not fired.
		dojo.forEach(this.options, function(i){
			i.selected = !i.selected;
		});
		this._updateSelection();
	},

	_setDisabledAttr: function(value){
		// summary:
		//		Disable (or enable) all the children as well
		this.inherited(arguments);
		dojo.forEach(this._getChildren(), function(node){
			if(node && node.attr){
				node.attr("disabled", value);
			}
		});
	},

	_setReadOnlyAttr: function(value){
		// summary:
		//		Sets read only (or unsets) all the children as well
		if("readOnly" in this.attributeMap){
			this._attrToDom("readOnly", value);
		}
		this.readOnly = value;
		dojo.forEach(this._getChildren(), function(node){
			if(node && node.attr){
				node.attr("readOnly", value);
			}
		});
		this._setStateClass();
	},

	uninitialize: function(){
		// Make sure these children are destroyed
		dojo.forEach(this._getChildren(), function(child){
			child.destroyRecursive();
		});
	}
});
<commit_msg>Fixes #8365 - support disabled options in checked multi select<commit_after>dojo.provide("dojox.form.CheckedMultiSelect");

dojo.require("dijit.form.CheckBox");
dojo.require("dojox.form._FormSelectWidget");

dojo.declare("dojox.form._CheckedMultiSelectItem",
	[dijit._Widget, dijit._Templated],
	{
	// summary:
	//		The individual items for a CheckedMultiSelect

	widgetsInTemplate: true,
	templatePath: dojo.moduleUrl("dojox.form", "resources/_CheckedMultiSelectItem.html"),

	baseClass: "dojoxMultiSelectItem",

	// option: dojox.form.__SelectOption
	//		The option that is associated with this item
	option: null,
	parent: null,

	// disabled: boolean
	//		Whether or not this widget is disabled
	disabled: false,

	// readOnly: boolean
	//		Whether or not this widget is readOnly
	readOnly: false,

	postMixInProperties: function(){
		// summary:
		//		Set the appropriate _subClass value - based on if we are multi-
		//		or single-select
		if(this.parent._multiValue){
			this._type = {type: "checkbox", baseClass: "dijitCheckBox"};
		}else{
			this._type = {type: "radio", baseClass: "dijitRadio"};
		}
		this.disabled = this.option.disabled||false;
		this.inherited(arguments);
	},

	postCreate: function(){
		// summary:
		//		Set innerHTML here - since the template gets messed up sometimes
		//		with rich text
		this.inherited(arguments);
		this.labelNode.innerHTML = this.option.label;
	},

	_changeBox: function(){
		// summary:
		//		Called to force the select to match the state of the check box
		//		(only on click of the checkbox)  Radio-based calls _setValueAttr
		//		instead.
		if(this.attr("disabled") || this.attr("readOnly")){ return; }
		if(this.parent._multiValue){
			this.option.selected = this.checkBox.attr('value') && true;
		}else{
			this.parent.attr('value', this.option.value);
		}
		// fire the parent's change
		this.parent._updateSelection();

		// refocus the parent
		this.parent.focus();
	},

	_onMouse: function(e){
		// summary:
		//		Sets the hover state depending on mouse state (passes through
		//		to the check box)
		if(this.attr("disabled") || this.attr("readOnly")){
			dojo.stopEvent(e);
		}else{
			this.checkBox._onMouse(e);
		}
	},

	_onClick: function(e){
		// summary:
		//		Sets the click state (passes through to the check box)
		if(this.attr("disabled") || this.attr("readOnly")){
			dojo.stopEvent(e);
		}else{
			this.checkBox._onClick(e);
		}
	},

	_updateBox: function(){
		// summary:
		//		Called to force the box to match the state of the select
		this.checkBox.attr('value', this.option.selected);
	},

	_setDisabledAttr: function(value){
		// summary:
		//		Disables (or enables) all the children as well
		this.disabled = value||this.option.disabled;
		this.checkBox.attr("disabled", this.disabled);
		dojo.toggleClass(this.domNode, "dojoxMultiSelectDisabled", this.disabled);
	},

	_setReadOnlyAttr: function(value){
		// summary:
		//		Sets read only (or unsets) all the children as well
		this.checkBox.attr("readOnly", value);
		this.checkBox._setStateClass();
		this.readOnly = value;
	}
});

dojo.declare("dojox.form.CheckedMultiSelect", dojox.form._FormSelectWidget, {
	// summary:
	//		Extends the core dijit MultiSelect to provide a "checkbox" selector

	templateString: "",
	templatePath: dojo.moduleUrl("dojox.form", "resources/CheckedMultiSelect.html"),

	baseClass: "dojoxMultiSelect",

	_mouseDown: function(e){
		// summary:
		//		Cancels the mousedown event to prevent others from stealing
		//		focus
		dojo.stopEvent(e);
	},

	_addOptionItem: function(/* dojox.form.__SelectOption */ option){
		this.wrapperDiv.appendChild(new dojox.form._CheckedMultiSelectItem({
			option: option,
			parent: this
		}).domNode);
	},

	_updateSelection: function(){
		this.inherited(arguments);
		dojo.forEach(this._getChildren(), function(c){ c._updateBox(); });
	},

	_getChildren: function(){
		return dojo.map(this.wrapperDiv.childNodes, function(n){
			return dijit.byNode(n);
		});
	},

	invertSelection: function(onChange){
		// summary: Invert the selection
		// onChange: Boolean
		//		If null, onChange is not fired.
		dojo.forEach(this.options, function(i){
			i.selected = !i.selected;
		});
		this._updateSelection();
	},

	_setDisabledAttr: function(value){
		// summary:
		//		Disable (or enable) all the children as well
		this.inherited(arguments);
		dojo.forEach(this._getChildren(), function(node){
			if(node && node.attr){
				node.attr("disabled", value);
			}
		});
	},

	_setReadOnlyAttr: function(value){
		// summary:
		//		Sets read only (or unsets) all the children as well
		if("readOnly" in this.attributeMap){
			this._attrToDom("readOnly", value);
		}
		this.readOnly = value;
		dojo.forEach(this._getChildren(), function(node){
			if(node && node.attr){
				node.attr("readOnly", value);
			}
		});
		this._setStateClass();
	},

	uninitialize: function(){
		// Make sure these children are destroyed
		dojo.forEach(this._getChildren(), function(child){
			child.destroyRecursive();
		});
	}
});
<|endoftext|>


<commit_before>/**
 *  This is just a sample file!
 *  Copy it to /app/src/grunt-local/ to have an effect!
 */
module.exports = {
    ignore: [
		/^The “tt” element is obsolete./,
        /^An “img” element must have an “alt”/
    ]
};
<commit_msg>Tabs -> spaces<commit_after>/**
 *  This is just a sample file!
 *  Copy it to /app/src/grunt-local/ to have an effect!
 */
module.exports = {
    ignore: [
        /^The “tt” element is obsolete./,
        /^An “img” element must have an “alt”/
    ]
};
<|endoftext|>


<commit_before>hqDefine("dhis2/js/dataset_map", [
    "jquery",
    "underscore",
    "hqwebapp/js/initial_page_data",
    "hqwebapp/js/crud_paginated_list_init",
    "hqwebapp/js/widgets",
], function (
    $,
    _,
    initialPageData
) {
    $(function () {
        var $sendNowResult = $('#send-now-result');
        var $remoteLogsLink = $('#remote-logs');
        $remoteLogsLink.hide();

        var handleSuccess = function (response) {
            $sendNowResult.removeClass("hide text-danger text-success");
            if (response.success) {
                $sendNowResult.addClass("text-success");
            } else {
                $sendNowResult.addClass("text-danger");
            }
            $sendNowResult.text(gettext('DHIS2 response: ') + response.text);
            if (response.log_url) {
                $remoteLogsLink.attr('href', response.log_url);
                $remoteLogsLink.show();
            }
        };

        var handleFailure = function (resp) {
            $sendNowResult
                .removeClass("hide text-success")
                .addClass("text-danger");
            $sendNowResult.text(
                gettext('CommCare HQ was unable to send the DataSet: ')
                + (resp.responseJSON ? resp.responseJSON['error'] : resp.statusText)
            );
            if (resp.responseJSON) {
                $remoteLogsLink.attr('href', resp.responseJSON['log_url']);
                $remoteLogsLink.show();
            }
        };

        sendNow = function (dataSetMapId) {
            $.post({
                url: initialPageData.reverse("send_dataset_now", dataSetMapId),
                success: handleSuccess,
                error: handleFailure,
            });
        };
    });
});
<commit_msg>Bundle var declaration<commit_after>hqDefine("dhis2/js/dataset_map", [
    "jquery",
    "underscore",
    "hqwebapp/js/initial_page_data",
    "hqwebapp/js/crud_paginated_list_init",
    "hqwebapp/js/widgets",
], function (
    $,
    _,
    initialPageData
) {
    $(function () {
        var $sendNowResult = $('#send-now-result'), $remoteLogsLink = $('#remote-logs');
        $remoteLogsLink.hide();

        var handleSuccess = function (response) {
            $sendNowResult.removeClass("hide text-danger text-success");
            if (response.success) {
                $sendNowResult.addClass("text-success");
            } else {
                $sendNowResult.addClass("text-danger");
            }
            $sendNowResult.text(gettext('DHIS2 response: ') + response.text);
            if (response.log_url) {
                $remoteLogsLink.attr('href', response.log_url);
                $remoteLogsLink.show();
            }
        };

        var handleFailure = function (resp) {
            $sendNowResult
                .removeClass("hide text-success")
                .addClass("text-danger");
            $sendNowResult.text(
                gettext('CommCare HQ was unable to send the DataSet: ')
                + (resp.responseJSON ? resp.responseJSON['error'] : resp.statusText)
            );
            if (resp.responseJSON) {
                $remoteLogsLink.attr('href', resp.responseJSON['log_url']);
                $remoteLogsLink.show();
            }
        };

        sendNow = function (dataSetMapId) {
            $.post({
                url: initialPageData.reverse("send_dataset_now", dataSetMapId),
                success: handleSuccess,
                error: handleFailure,
            });
        };
    });
});
<|endoftext|>


<commit_before>/**
 * Copyright 2015 Darshak Parikh
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var isStream = require('is-stream');
var magic = require('stream-mmmagic');
var request = require('request');
var stream = require('stream');
var types = require('./types.json');
var _ = require('lodash');

/**
 * Get the type of message based on contents
 * @param  {stream|string}   content  content to check
 * @param  {Function} callback Callback function
 */
exports.getMessageType = function (content, callback) {
  'use strict';
  if (isStream.readable(content)) {
    // Hack to keep `magic` from ruining the stream
    var contentCopy = new stream.PassThrough();
    content.pipe(contentCopy);

    magic(contentCopy, function (err, mime) {
      if (err) {
        console.log(err);
      }
      if (_.contains(types.image, mime.type)) {
        callback('image');
      } else if (_.contains(types.audio, mime.type)) {
        callback('audio');
      } else if (_.contains(types.video, mime.type)) {
        callback('video');
      } else {
        callback('document');
      }
    });
  } else if (_.isString(contentCopy)) {
    callback('text');
  } else {
    console.error('Couldn\'t determine type of content. Please pass a string or a readable stream.');
  }
};

/**
 * Generic method to send HTTPS requests
 * @param  {Object}   params   form data
 * @param  {Function} callback Callback function
 */
exports.sendRequest = function (params, callback) {
  'use strict';
  request.post(params, function (err, res, body) {
    if (err) {
      console.error(err);
    }
    if (callback) {
      callback(JSON.parse(body));
    }
  });
};
<commit_msg>Fix string check<commit_after>/**
 * Copyright 2015 Darshak Parikh
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var isStream = require('is-stream');
var magic = require('stream-mmmagic');
var request = require('request');
var stream = require('stream');
var types = require('./types.json');
var _ = require('lodash');

/**
 * Get the type of message based on contents
 * @param  {stream|string}   content  content to check
 * @param  {Function} callback Callback function
 */
exports.getMessageType = function (content, callback) {
  'use strict';
  if (isStream.readable(content)) {
    // Hack to keep `magic` from ruining the stream
    var contentCopy = new stream.PassThrough();
    content.pipe(contentCopy);

    magic(contentCopy, function (err, mime) {
      if (err) {
        console.log(err);
      }
      if (_.contains(types.image, mime.type)) {
        callback('image');
      } else if (_.contains(types.audio, mime.type)) {
        callback('audio');
      } else if (_.contains(types.video, mime.type)) {
        callback('video');
      } else {
        callback('document');
      }
    });
  } else if (_.isString(content)) {
    callback('text');
  } else {
    console.error('Couldn\'t determine type of content. Please pass a string or a readable stream.');
  }
};

/**
 * Generic method to send HTTPS requests
 * @param  {Object}   params   form data
 * @param  {Function} callback Callback function
 */
exports.sendRequest = function (params, callback) {
  'use strict';
  request.post(params, function (err, res, body) {
    if (err) {
      console.error(err);
    }
    if (callback) {
      callback(JSON.parse(body));
    }
  });
};
<|endoftext|>


<commit_before>(function () {
  'use strict';
  angular.module('bingo', [])
  .factory('BingoCardService', [function () {
    var ITEMS = [
      'chart showing mobile use exploding',
      'Gartner Hype Cycle',
      'word/tag cloud',
      'meme',
      'presenter makes joke about his/her baldness',
      'demo fails due to poor wi-fi',
      'speaker asks everyone to get off wi-fi',
      'talk too crowded, coding in lobby',
      'slide deck crashes, speaker has to improvise',
      'presentation about power and versatility of HTML5 using PowerPoint or Keynote deck',
      'Prezi',
      'Steve Souders is name checked',
      'Paul Irish is name checked',
      'more than three presenters on stage, all white dudes',
      '"awesome" used twice in less than 60 seconds',
      '"hot" or "hottest" used without apparent irony',
      'presenter makes joke about his/her age',
      'presenter jokes about audience sleeping',
      'presenter mentions yet another JS MV* framework you never heard of before',
      'presenter cites actual text from a W3C standard',
      '#bada55',
      'attendee wearing suspenders',
      'presenter does not show up',
      'presenter drops f-bomb',
      '"dirty checking" pun',
      'mind blown by slide deck animations',
      'feeling like the dumbest person in the room',
      'feeling like the smartest person in the room',
      'thinking "Best. Something. Ever." and actualy meaning it',
      'at a CSS talk when you thought it would be a JS talk',
      'at a JS talk when you thought it would be a CSS talk',
      'high fiving another attendee',
      'some annoyance defused by recalling low ticket price',
      't-shirt schwag',
      'sticker schwag',
      'WAT?!',
      'speaker calls out primary sponsor for doing something wrong',
      'watch amazing session only to be told at the end that your target browsers don\'t support it',
    ];

    return {
      newCard: function () {
        var rv = [];
        var items = ITEMS.slice(0);
        var index;

        for(var i=0; i<5 ; i++){
          rv[i]=[];
          for(var j=0; j<5; j++) {
            if (i==2 && j==2) {
              rv[i][j] = "Free";
            } else {
              index = Math.floor(Math.random()*items.length);
              rv[i][j] = items.splice(index,1)[0];
            }
          }
        }

        return rv;
      }
    };
  }])
  .controller(
    'bingoController',
    ['$scope', 'BingoCardService', function ($scope, BingoCardService) {

      $scope.newCard = function () {
        $scope.card = {};
        $scope.card.rows = BingoCardService.newCard();
        $scope.card.header = ['B', 'I', 'N', 'G', 'O'];
      };

      $scope.newCard();
    }]
  );
}());<commit_msg>add "phablet"<commit_after>(function () {
  'use strict';
  angular.module('bingo', [])
  .factory('BingoCardService', [function () {
    var ITEMS = [
      'chart showing mobile use exploding',
      'Gartner Hype Cycle',
      'word/tag cloud',
      'meme',
      'presenter makes joke about his/her baldness',
      'demo fails due to poor wi-fi',
      'speaker asks everyone to get off wi-fi',
      'talk too crowded, coding in lobby',
      'slide deck crashes, speaker has to improvise',
      'presentation about power and versatility of HTML5 using PowerPoint or Keynote deck',
      'Prezi',
      'Steve Souders is name checked',
      'Paul Irish is name checked',
      'more than three presenters on stage, all white dudes',
      '"awesome" used twice in less than 60 seconds',
      '"hot" or "hottest" used without apparent irony',
      'presenter makes joke about his/her age',
      'presenter jokes about audience sleeping',
      'presenter mentions yet another JS MV* framework you never heard of before',
      'presenter cites actual text from a W3C standard',
      '#bada55',
      'attendee wearing suspenders',
      'presenter does not show up',
      'presenter drops f-bomb',
      '"dirty checking" pun',
      'mind blown by slide deck animations',
      'feeling like the dumbest person in the room',
      'feeling like the smartest person in the room',
      'thinking "Best. Something. Ever." and actualy meaning it',
      'at a CSS talk when you thought it would be a JS talk',
      'at a JS talk when you thought it would be a CSS talk',
      'high fiving another attendee',
      'some annoyance defused by recalling low ticket price',
      't-shirt schwag',
      'sticker schwag',
      'WAT?!',
      'speaker calls out primary sponsor for doing something wrong',
      'watch amazing session only to be told at the end that your target browsers don\'t support it',
      '"phablet" used without hint of irony',
    ];

    return {
      newCard: function () {
        var rv = [];
        var items = ITEMS.slice(0);
        var index;

        for(var i=0; i<5 ; i++){
          rv[i]=[];
          for(var j=0; j<5; j++) {
            if (i==2 && j==2) {
              rv[i][j] = "Free";
            } else {
              index = Math.floor(Math.random()*items.length);
              rv[i][j] = items.splice(index,1)[0];
            }
          }
        }

        return rv;
      }
    };
  }])
  .controller(
    'bingoController',
    ['$scope', 'BingoCardService', function ($scope, BingoCardService) {

      $scope.newCard = function () {
        $scope.card = {};
        $scope.card.rows = BingoCardService.newCard();
        $scope.card.header = ['B', 'I', 'N', 'G', 'O'];
      };

      $scope.newCard();
    }]
  );
}());<|endoftext|>


<commit_before>'use strict';
var logger = require('logger');
var mailService = require('services/mailService');

const DEFAULT_TEMPLATE = 'forest-change-notification';
const TEMPLATE_MAP = {
  'viirs-active-fires': 'fires-notification',
  'imazon-alerts': 'forest-change-imazon-alerts',
  'story': 'stories-alerts',
  'forma-alerts': 'forest-change-notification',
  'forma250GFW': 'forest-change-notification',
  'terrai-alerts': 'forest-change-notification'

};

class EmailPublisher {

  static * publish(subscription, results, layer) {
      logger.info('Publishing email with results', results);
    let template = TEMPLATE_MAP[layer.slug] || DEFAULT_TEMPLATE;
    let language = subscription.language.toLowerCase().replace(/_/g, '-');
    template = `${template}-${language}`;
    logger.info('MAIL TEMPLATE', template);
    let recipients = [{
          address: {
            email: subscription.resource.content
          }
        }];
    mailService.sendMail(template, results, recipients);
  }

  static sendStats(emails, stats) {
    logger.warn('Publishing email with stats', stats);
    let template = 'subscriptions-stats';
    logger.warn('MAIL TEMPLATE', template);
    let recipients = emails.map(el => ({address: {email: el}}));
    mailService.sendMail(template, stats, recipients);
  }

}

module.exports = EmailPublisher;
<commit_msg>glad-alerts missing key<commit_after>'use strict';
var logger = require('logger');
var mailService = require('services/mailService');

const DEFAULT_TEMPLATE = 'forest-change-notification';
const TEMPLATE_MAP = {
  'viirs-active-fires': 'fires-notification',
  'imazon-alerts': 'forest-change-imazon-alerts',
  'story': 'stories-alerts',
  'forma-alerts': 'forest-change-notification',
  'forma250GFW': 'forest-change-notification',
  'terrai-alerts': 'forest-change-notification',
  'glad-alerts':'forest-change-notification'
};

class EmailPublisher {

  static * publish(subscription, results, layer) {
      logger.info('Publishing email with results', results);
    let template = TEMPLATE_MAP[layer.slug] || DEFAULT_TEMPLATE;
    let language = subscription.language.toLowerCase().replace(/_/g, '-');
    template = `${template}-${language}`;
    logger.info('MAIL TEMPLATE', template);
    let recipients = [{
          address: {
            email: subscription.resource.content
          }
        }];
    mailService.sendMail(template, results, recipients);
  }

  static sendStats(emails, stats) {
    logger.warn('Publishing email with stats', stats);
    let template = 'subscriptions-stats';
    logger.warn('MAIL TEMPLATE', template);
    let recipients = emails.map(el => ({address: {email: el}}));
    mailService.sendMail(template, stats, recipients);
  }

}

module.exports = EmailPublisher;
<|endoftext|>


<commit_before>var Vue = require('vue');
var View = require('../src/index.js');

Vue.config.debug = true;

var view = new View({
  theme: 'lightBlue',
  skin: 'bar',
  position: 'mc',
  serviceName: 'Mention',
  translation: {
    FOLLOWUP_PROMOTER: 'Thats awesome!',
    DETAILS: 'We\' like to hear more',
    REASONS: ['Too many mentions are missed', 'Mention is too expensive', 'Everything is perfect', 'Very important features are missing']
  }
});
view.on('submit', function() {
  console.log('submit', view.rating, view.feedback, view.reason);
});
view.on('dismiss', function() {
  console.log('dismiss');
});
view.show();

// expose view for experiments
window.view = view;
<commit_msg>rating category in example<commit_after>var Vue = require('vue');
var View = require('../src/index.js');

Vue.config.debug = true;

var view = new View({
  theme: 'lightBlue',
  skin: 'bar',
  position: 'mc',
  serviceName: 'Mention',
  translation: {
    THANKS_IMPROVE_PROMOTER: 'Thats awesome!',
    DETAILS: 'We\' like to hear more',
    REASONS: ['Too many mentions are missed', 'Mention is too expensive', 'Everything is perfect', 'Very important features are missing']
  }
});
view.on('submit', function() {
  console.log('submit', view.rating, view.feedback, view.reason);
});
view.on('dismiss', function() {
  console.log('dismiss');
});
view.show();

// expose view for experiments
window.view = view;
<|endoftext|>


<commit_before>/**
 * Created by sanjeevbudha on 6/30/16.
 */

function deleteBreed(id){

    var mode ='delete';

    var n = noty({
        layout: 'center',
        text: "Are you sure you want delete? ",
        killer: true,
        buttons: [
            {
                addClass: 'btn btn-primary', text: 'Ok', onClick: function ($noty) {
                n.close();
                $.ajax({
                    type:"POST",
                    url:'../controller/breedHandler.php',
                    data:"mode="+mode+"&id="+id,
                    success:function(data){
                        var data = JSON.parse(data);

                        if(data.message=='success'){
                            displayMessage("Successfully Deleted","success");
                            customReloadWindow(2000)
                        }
                    },error: function (er) {
                        alert("Error while Creating" +er.responseText);
                    }
                });
                return false;
            }
            },
            {
                addClass: 'btn btn-danger', text: 'Cancel', onClick: function ($noty) {
                n.close();
            }
            }
        ]
    })

}<commit_msg>updated<commit_after>/**
 * Created by sanjeevbudha on 6/30/16.
 */

function deleteBreed(id){

    var mode ='delete';

    alert(window.location.href);
    var n = noty({
        layout: 'center',
        text: "Are you sure you want delete? ",
        killer: true,
        buttons: [
            {
                addClass: 'btn btn-primary', text: 'Ok', onClick: function ($noty) {
                n.close();
                $.ajax({
                    type:"POST",
                    url:'../controller/breedHandler.php',
                    data:"mode="+mode+"&id="+id,
                    success:function(data){
                        var data = JSON.parse(data);

                        if(data.message=='success'){
                            displayMessage("Successfully Deleted","success");
                            customReloadWindow(2000)
                        }
                    },error: function (er) {
                        alert("Error while Creating" +er.responseText);
                    }
                });
                return false;
            }
            },
            {
                addClass: 'btn btn-danger', text: 'Cancel', onClick: function ($noty) {
                n.close();
            }
            }
        ]
    })

}<|endoftext|>


<commit_before>'use strict';

const Router = require('express').Router;
const debug = require('debug')('ht:hospital-router');
const jsonParser = require('body-parser').json();
const bearerAuth = require('../lib/bearer-auth-middleware');
const Profile = require('../model/profile');

const profileRouter = module.exports = Router();

profileRouter.post('/api/hospital/hospitalID/profile', bearerAuth, jsonParser, function(req, res, next){
  debug('hit POST route /api/hospital/hospitalID/profile');
});
<commit_msg>added more changes to profile router<commit_after>'use strict';

const Router = require('express').Router;
const debug = require('debug')('ht:hospital-router');
const jsonParser = require('body-parser').json();
const bearerAuth = require('../lib/bearer-auth-middleware');
const Profile = require('../model/profile');

const profileRouter = module.exports = Router();

profileRouter.post('/api/hospital/hospitalID/profile', bearerAuth, jsonParser, function(req, res, next){
  debug('hit POST route /api/hospital/hospitalID/profile');
  new Profile(req.body).save()
  .then( profile => res.json(profile))
  .catch(next);
});
<|endoftext|>