<commit_before>/**
 * A module handling the controller and view for the chat feature.
 */
var chat = angular.module('chat', ['auth']);

chat.controller('ChatCtrl', ['$scope', '$rootScope', '$routeParams', 'socket', 'authSrv', 'nicknameSrv',
  function ($scope, $rootScope, $routeParams, socket, authSrv, nicknameSrv) {
    $rootScope.radioid = $scope.radioId = $routeParams.username;

    $scope.chat = {};
    $scope.chat.messages = [];
    $scope.$parent.isBroadcasterConnected = true;

    authSrv.getCurrentUser(function (user) {
      if (user && user.username) {
        socket.emit('join_radio', {
          radioid: $rootScope.radioid,
          username: user.username,
          isBroadcaster: user.username === $rootScope.radioid
        });
      } else {
        socket.emit('join_radio', {
          radioid: $rootScope.radioid,
          isBroadcaster: false,
          username: null
        });
      }
    });

    $scope.chat.send = function () {
      authSrv.getNickname(nicknameSrv).then(function (nickname) {
        if (nickname && $scope.chat.message) {
          socket.emit('send_message', {
            nickname: nickname,
            radioid: $rootScope.radioid,
            message: $scope.chat.message
          });
          $scope.chat.message = '';
        }
      });
    };

    socket.on('update_chat', function (data) {
      $scope.chat.messages.push(data.message);
    });

    socket.on('update_broadcaster_status', function (data) {
      $scope.$parent.isBroadcasterConnected = data.isBroadcasterConnected;
    });
  }]);

chat.directive('chatWindow', function () {
  return {
    restrict: 'E',
    templateUrl: 'modules/chat/chat.html'
  };
});

// Used to scroll the chat display individually from the entire chatWindow directive
chat.directive('chatOutput', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attr) {
      scope.$watchCollection(attr.chatOutput, function () {
        element[0].scrollTop = element[0].scrollHeight;
      });
    }
  };
});
<commit_msg>Enforce listeners to enter nickname as soon as they enter the channel<commit_after>/**
 * A module handling the controller and view for the chat feature.
 */
var chat = angular.module('chat', ['auth']);

chat.controller('ChatCtrl', ['$scope', '$rootScope', '$routeParams', 'socket', 'authSrv', 'nicknameSrv',
  function ($scope, $rootScope, $routeParams, socket, authSrv, nicknameSrv) {
    $rootScope.radioid = $scope.radioId = $routeParams.username;

    $scope.chat = {};
    $scope.chat.messages = [];
    $scope.$parent.isBroadcasterConnected = true;

    authSrv.getNickname(nicknameSrv);

    authSrv.getCurrentUser(function (user) {
      if (user && user.username) {
        socket.emit('join_radio', {
          radioid: $rootScope.radioid,
          username: user.username,
          isBroadcaster: user.username === $rootScope.radioid
        });
      } else {
        socket.emit('join_radio', {
          radioid: $rootScope.radioid,
          isBroadcaster: false,
          username: null
        });
      }
    });

    $scope.chat.send = function () {
      authSrv.getNickname(nicknameSrv).then(function (nickname) {
        if (nickname && $scope.chat.message) {
          socket.emit('send_message', {
            nickname: nickname,
            radioid: $rootScope.radioid,
            message: $scope.chat.message
          });
          $scope.chat.message = '';
        }
      });
    };

    socket.on('update_chat', function (data) {
      $scope.chat.messages.push(data.message);
    });

    socket.on('update_broadcaster_status', function (data) {
      $scope.$parent.isBroadcasterConnected = data.isBroadcasterConnected;
    });
  }]);

chat.directive('chatWindow', function () {
  return {
    restrict: 'E',
    templateUrl: 'modules/chat/chat.html'
  };
});

// Used to scroll the chat display individually from the entire chatWindow directive
chat.directive('chatOutput', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attr) {
      scope.$watchCollection(attr.chatOutput, function () {
        element[0].scrollTop = element[0].scrollHeight;
      });
    }
  };
});
<|endoftext|>


<commit_before>var pencilEnlargement = {
    start: function(game) {
        game.state.add('play', this.Play)
        game.state.start('play')
    }
}

pencilEnlargement.Pencil = function(game) {
    var scale = 1
    var scaleIncrement = 0.1
    var scaleDecrement = 0.3
    var sprite = this.sprite = new Phaser.Sprite(game, game.world.centerX, game.world.centerY, 'pencil')
    sprite.anchor.x = 0.5
    sprite.anchor.y = 0.5
    sprite.inputEnabled = true
    sprite.events.onInputDown.add(function () {
        scale += scaleIncrement
    })
    sprite.update = function () {
        if (scale > 1) {
            scale -= scaleDecrement * game.time.physicsElapsed
        }
        sprite.scale.x = scale
        sprite.scale.y = scale
    }
}

pencilEnlargement.Play = function() {
    this.pencil = null
}
pencilEnlargement.Play.prototype = {
    init: function() {
        this.game.stage.backgroundColor = '#fff'
        this.input.maxPointers = 1
    },
    preload: function() {
        this.load.image('pencil', 'pencil.png')
    },
    create: function() {
        this.pencil = new pencilEnlargement.Pencil(this.game)
        this.game.add.existing(this.pencil.sprite)
    },
}

;(function () {
    var game = new Phaser.Game('100', '100')
    pencilEnlargement.start(game)
}())
<commit_msg>added title and help text<commit_after>var pencilEnlargement = {
    start: function(game) {
        game.state.add('play', this.Play)
        game.state.start('play')
    }
}

pencilEnlargement.Pencil = function(game) {
    var scale = 1
    var scaleIncrement = 0.1
    var scaleDecrement = 0.3
    var sprite = this.sprite = new Phaser.Sprite(game, game.world.centerX, game.world.centerY, 'pencil')
    sprite.anchor.x = 0.5
    sprite.anchor.y = 0.5
    sprite.inputEnabled = true
    sprite.events.onInputDown.add(function () {
        scale += scaleIncrement
    })
    sprite.update = function () {
        if (scale > 1) {
            scale -= scaleDecrement * game.time.physicsElapsed
        }
        sprite.scale.x = scale
        sprite.scale.y = scale
    }
}

pencilEnlargement.Play = function() {
    this.pencil = null
}
pencilEnlargement.Play.prototype = {
    init: function() {
        this.game.stage.backgroundColor = 0xffffff
        this.input.maxPointers = 1
    },
    preload: function() {
        this.load.image('pencil', 'pencil.png')
    },
    create: function() {
        this.game.add.text(25, 20, 'Pencil Enlargement', {
            font: '30pt Georgia',
        })
        this.game.add.text(25, 70, 'It works! Add inches in seconds!', {
            font: '15pt Georgia',
            fill: 'gray',
        })
        this.game.add.text(25, this.game.world.height - 100, 'Click the pencil to make it bigger.\nSpeed and persistence bring best results.\nEnlarge until satisfied, or till it crashes the browser or something.', {
            font: '12pt Georgia',
            fill: 'gray',
        })
        this.pencil = new pencilEnlargement.Pencil(this.game)
        this.game.add.existing(this.pencil.sprite)
    },
}

;(function () {
    var game = new Phaser.Game('100', '100')
    pencilEnlargement.start(game)
}())
<|endoftext|>


<commit_before>let document_previews;
$(function(){

    // Display the loading overlay on the "Previews" section
    start_loading("#previews");

    // Send a request for the document preview data
    $.ajax({type: "GET", url: "document-previews"})

        // If the request was successful, create a preview for each active
        // document
        .done(function(response){
            document_previews = parse_json(response);
            initialize_document_previews(response);
        })

        // If the request failed, display an error and "Loading Failed" text
        .fail(function(){
            error("Failed to retrieve the document previews.");
            add_text_overlay("#previews", "Loading Failed");
            enable("#preview-button, #apply-button");
        });

    // Perform the cutting if the "Preview" or "Apply" button is pressed
    $("#preview-button").click(function(){ cut("preview"); });
    $("#apply-button").click(function(){ cut("apply"); });

    // Load the appropriate content for the "Cut Settings" section when the
    // "Cut Mode" setting is changed
    $("#cut-mode-section input").change(load_cut_settings_section);

    // Initialize the "Tokenize", "Normalize", and "Cull" tooltips
    initialize_tooltips();

    // Initialize the walkthrough
    initialize_walkthrough(walkthrough);
});

/**
 * Loads the appropriate content for the "Cut Settings" section.
 */
let cut_mode;
let previous_cut_mode = "Default";
function load_cut_settings_section(){

    // Return if the same cut mode was selected
    cut_mode = $("#cut-mode-grid input:checked").val();
    if(cut_mode !== "Segments" &&
        cut_mode !== "Milestones") cut_mode = "Default";
    if(cut_mode === previous_cut_mode) return;

    // Hide the cut settings
    let cut_settings_grid_element = $("#cut-settings-grid");
    cut_settings_grid_element.css("opacity", "0");

    let segment_text = $("#segment-size-label")

    // If the cut mode is set to "Segments"...
    if(cut_mode === "Segments"){
        previous_cut_mode = "Segments";
        hide(`#milestone-input, #overlap-input,
            #merge-threshold-input, #segment-size-tooltip-button`);
        segment_text.text("Number of Segments")
        show("#segment-size-input, #number-of-segments-tooltip-button");
    }

    // Otherwise, if the cut mode is set to "Milestones"...
    else if(cut_mode === "Milestones"){
        previous_cut_mode = "Milestones";
        hide(`#segment-size-input, #overlap-input,
            #merge-threshold-input`);
        show("#milestone-input");
    }

    // Otherwise, if the cut mode is set to "Tokens", "Characters", or
    // "Lines"...
    else {
        previous_cut_mode = "Default";
        hide("#milestone-input, #number-of-segments-tooltip-button");
        segment_text.text("Segment Size")
        show(`#segment-size-input, #overlap-input,
            #merge-threshold-input, #segment-size-tooltip-button`);
    }

    // Set the legacy "cutByMS" input if the cut mode is "milestone"
    $("#cut-by-milestone-input").val(cut_mode === "Milestones" ? "on" : "off")

    // Fade in the settings
    fade_in(cut_settings_grid_element);
}

/**
 * Cuts the active documents.
 * @param {string} action: The cut operation action ("preview" or "apply").
 */
function cut(action){

    // Validate the inputs. If the inputs are invalid, return
    if(!validate_inputs()) return;

    // Remove any existing error messages
    remove_errors();

    // Display the loading overlay and disable the buttons on the document
    // previews section
    start_document_previews_loading();

    // Load the form data and add an entry for the cut action
    let form_data = new FormData($("form")[0]);
    form_data.append("action", action);

    // Create a copy of the cut settings for each document to satisfy legacy
    // requirements
    let options = ["cut_mode", "segment_size", "overlap",
        "merge_threshold", "milestone"]
    for(const document of document_previews)
        for(const option of options)
            form_data.append(option+'_'+document[0], form_data.get(option));

    // Send the cut request
    $.ajax({
        type: "POST",
        url: "cut/execute",
        processData: false,
        contentType: false,
        data: form_data
    })

    // If the request is successful, update the document previews with the
    // cut previews returned in the response
    .done(create_document_previews)

    // If the request failed, display an error and remove the loading overlay
    .fail(function(){
        error("Failed to cut the documents.");
        add_text_overlay("#previews", "Loading Failed");
        enable("#preview-button, #apply-button");
    })
}

/**
 * Creates the document previews.
 * @param {string} response: The response containing the new previews.
 */
function create_document_previews(response){
    let previews = parse_json(response);

    // If there are no previews, display "No Previews" text
    if(!previews.length) add_text_overlay("#previews", "No Previews");

    // Otherwise, create the previews
    else for(const preview of previews)
        create_document_preview(preview[2], preview[3]);

    // Remove the loading overlay, fade in the previews, and enable the
    // buttons for the document previews section
    finish_document_previews_loading();
}

/**
 * Validate the inputs.
 * @returns {boolean}: Whether the inputs are valid.
 */
function validate_inputs(){

    // "Milestone"
    if(cut_mode === "Milestones"){
        if($("#milestone-input input").val().length <= 0){
            error("A milestone must be provided.", "#milestone-input input");
            return false;
        }
        return true;
    }

    // "Segment size"
    let segment_size = $("#segment-size-input input").val();
    let int_segment_size = parseInt(segment_size);
    if(!validate_number(segment_size, 1)){
        error("Invalid segment size.", "#segment-size-input input");
        return false;
    }

    // "Segments"
    if(cut_mode === "Segments") return true;

    // "Overlap"
    let overlap = $("#overlap-input input").val();
    let int_overlap = parseInt(overlap);
    if(!validate_number(overlap, 0)){
        error("Invalid overlap size.", "#overlap-input input");
        return false;
    }

    if(int_overlap >= int_segment_size){
        error(`The overlap cannot be greater than or equal to the segment
            size.`, "#overlap-input input");
        return false;
    }

    // "Merge threshold"
    if(!validate_number($("#merge-threshold-input input").val(), 0, 100)){
        error("Invalid merge threshold.", "#merge-threshold-input input");
        return false;
    }

    return true;
}

/**
 * Initialize the tooltips.
 */
function initialize_tooltips(){

    // "Cut Mode"
    create_tooltip("#cut-mode-tooltip-button", `Lexos uses spaces between
        tokens to determine where to cut documents into the specified number,
        so this tool may not work if you used Scrubber to strip white spaces
        from your documents.`);

    // "Segment Size"
    create_tooltip("#segment-size-tooltip-button", `A positive integer used to
        divide up the text. Either the number of letters, words, or lines
        per segment.`);

    // "Number of Segments"
    create_tooltip("#number-of-segments-tooltip-button", `The number of
        segments per document.`);

    // "Overlap"
    create_tooltip("#overlap-tooltip-button", `The amount of overlapping
        content at the start and end of segments. This number must be smaller
        than the segment size.`, true);

    // "Merge %"
    create_tooltip("#merge-threshold-tooltip-button", `The size of the last
        segment must be at least as large as the given percentage relative to
        other segment sizes. If the length of the last segment is below this
        threshold, it will be attached to the previous segment.`, true);

    // "Milestone"
    create_tooltip("#milestone-tooltip-button", `Split the document into
        segments at each appearance of the provided string. Child segments will not
        contain the Milestone delimiter.`);
}

/**
 * Initializes the walkthrough.
 */
function walkthrough(){

    let intro = introJs();
    intro.setOptions({steps: [
        {
            intro: `Welcome to the Cut page!`,
            position: "top",
        },
        {
            element: "#cut-mode-section",
            intro: `This is the Cut Mode section. Here you can specify how you
                would like to cut up your documents.`,
            position: "top",
        },
        {
            element: "#cut-settings-section",
            intro: `Based on your selection in the Cut Mode section, there are
                additional settings to fill out before you can initiate a
                cut.`,
            position: "top",
        },
        {
            element: "#preview-button",
            intro: `Similar to Scrub, you can preview your changes without
                saving them here.`,
            position: "top",
        },
        {
            element: "#apply-button",
            intro: `Unlike in Scrub, Apply works by creating new documents
                based on your cutting parameters. The original document is
                kept intact, but is deselected.`,
            position: "top",
        },
        {
            element: "#navbar-right",
            intro: `Once you're satisfied with your cut documents, you can
                move on to other pages in Prepare, Visualize, or Analyze.`,
            position: "bottom"
        },
        {
            intro: `This concludes the Cut walkthrough!`,
            position: "top",
        }
    ]});

    intro.start();
}
<commit_msg>Update active document count when cut is applied<commit_after>let document_previews;
$(function(){

    // Display the loading overlay on the "Previews" section
    start_loading("#previews");

    // Send a request for the document preview data
    $.ajax({type: "GET", url: "document-previews"})

        // If the request was successful, create a preview for each active
        // document
        .done(function(response){
            document_previews = parse_json(response);
            initialize_document_previews(response);
        })

        // If the request failed, display an error and "Loading Failed" text
        .fail(function(){
            error("Failed to retrieve the document previews.");
            add_text_overlay("#previews", "Loading Failed");
            enable("#preview-button, #apply-button");
        });

    // Perform the cutting if the "Preview" or "Apply" button is pressed
    $("#preview-button").click(function(){ cut("preview"); });
    $("#apply-button").click(function(){ cut("apply"); });

    // Load the appropriate content for the "Cut Settings" section when the
    // "Cut Mode" setting is changed
    $("#cut-mode-section input").change(load_cut_settings_section);

    // Initialize the "Tokenize", "Normalize", and "Cull" tooltips
    initialize_tooltips();

    // Initialize the walkthrough
    initialize_walkthrough(walkthrough);
});

/**
 * Loads the appropriate content for the "Cut Settings" section.
 */
let cut_mode;
let previous_cut_mode = "Default";
function load_cut_settings_section(){

    // Return if the same cut mode was selected
    cut_mode = $("#cut-mode-grid input:checked").val();
    if(cut_mode !== "Segments" &&
        cut_mode !== "Milestones") cut_mode = "Default";
    if(cut_mode === previous_cut_mode) return;

    // Hide the cut settings
    let cut_settings_grid_element = $("#cut-settings-grid");
    cut_settings_grid_element.css("opacity", "0");

    let segment_text = $("#segment-size-label")

    // If the cut mode is set to "Segments"...
    if(cut_mode === "Segments"){
        previous_cut_mode = "Segments";
        hide(`#milestone-input, #overlap-input,
            #merge-threshold-input, #segment-size-tooltip-button`);
        segment_text.text("Number of Segments")
        show("#segment-size-input, #number-of-segments-tooltip-button");
    }

    // Otherwise, if the cut mode is set to "Milestones"...
    else if(cut_mode === "Milestones"){
        previous_cut_mode = "Milestones";
        hide(`#segment-size-input, #overlap-input,
            #merge-threshold-input`);
        show("#milestone-input");
    }

    // Otherwise, if the cut mode is set to "Tokens", "Characters", or
    // "Lines"...
    else {
        previous_cut_mode = "Default";
        hide("#milestone-input, #number-of-segments-tooltip-button");
        segment_text.text("Segment Size")
        show(`#segment-size-input, #overlap-input,
            #merge-threshold-input, #segment-size-tooltip-button`);
    }

    // Set the legacy "cutByMS" input if the cut mode is "milestone"
    $("#cut-by-milestone-input").val(cut_mode === "Milestones" ? "on" : "off")

    // Fade in the settings
    fade_in(cut_settings_grid_element);
}

/**
 * Cuts the active documents.
 * @param {string} action: The cut operation action ("preview" or "apply").
 */
function cut(action){

    // Validate the inputs. If the inputs are invalid, return
    if(!validate_inputs()) return;

    // Remove any existing error messages
    remove_errors();

    // Display the loading overlay and disable the buttons on the document
    // previews section
    start_document_previews_loading();

    // Load the form data and add an entry for the cut action
    let form_data = new FormData($("form")[0]);
    form_data.append("action", action);

    // Create a copy of the cut settings for each document to satisfy legacy
    // requirements
    let options = ["cut_mode", "segment_size", "overlap",
        "merge_threshold", "milestone"]
    for(const document of document_previews)
        for(const option of options)
            form_data.append(option+'_'+document[0], form_data.get(option));

    // Send the cut request
    $.ajax({
        type: "POST",
        url: "cut/execute",
        processData: false,
        contentType: false,
        data: form_data
    })

    // If the request is successful, update the document previews with the
    // cut previews returned in the response
    .done(create_document_previews)

    // If the request failed, display an error and remove the loading overlay
    .fail(function(){
        error("Failed to cut the documents.");
        add_text_overlay("#previews", "Loading Failed");
        enable("#preview-button, #apply-button");
    })
}

/**
 * Creates the document previews.
 * @param {string} response: The response containing the new previews.
 */
function create_document_previews(response){
    let previews = parse_json(response);

    // If there are no previews, display "No Previews" text
    if(!previews.length) add_text_overlay("#previews", "No Previews");

    // Otherwise, create the previews
    else for(const preview of previews)
        create_document_preview(preview[2], preview[3]);

    // Remove the loading overlay, fade in the previews, and enable the
    // buttons for the document previews section
    finish_document_previews_loading();

    // Update the active document count
    update_active_document_count();
}

/**
 * Validate the inputs.
 * @returns {boolean}: Whether the inputs are valid.
 */
function validate_inputs(){

    // "Milestone"
    if(cut_mode === "Milestones"){
        if($("#milestone-input input").val().length <= 0){
            error("A milestone must be provided.", "#milestone-input input");
            return false;
        }
        return true;
    }

    // "Segment size"
    let segment_size = $("#segment-size-input input").val();
    let int_segment_size = parseInt(segment_size);
    if(!validate_number(segment_size, 1)){
        error("Invalid segment size.", "#segment-size-input input");
        return false;
    }

    // "Segments"
    if(cut_mode === "Segments") return true;

    // "Overlap"
    let overlap = $("#overlap-input input").val();
    let int_overlap = parseInt(overlap);
    if(!validate_number(overlap, 0)){
        error("Invalid overlap size.", "#overlap-input input");
        return false;
    }

    if(int_overlap >= int_segment_size){
        error(`The overlap cannot be greater than or equal to the segment
            size.`, "#overlap-input input");
        return false;
    }

    // "Merge threshold"
    if(!validate_number($("#merge-threshold-input input").val(), 0, 100)){
        error("Invalid merge threshold.", "#merge-threshold-input input");
        return false;
    }

    return true;
}

/**
 * Initialize the tooltips.
 */
function initialize_tooltips(){

    // "Cut Mode"
    create_tooltip("#cut-mode-tooltip-button", `Lexos uses spaces between
        tokens to determine where to cut documents into the specified number,
        so this tool may not work if you used Scrubber to strip white spaces
        from your documents.`);

    // "Segment Size"
    create_tooltip("#segment-size-tooltip-button", `A positive integer used to
        divide up the text. Either the number of letters, words, or lines
        per segment.`);

    // "Number of Segments"
    create_tooltip("#number-of-segments-tooltip-button", `The number of
        segments per document.`);

    // "Overlap"
    create_tooltip("#overlap-tooltip-button", `The amount of overlapping
        content at the start and end of segments. This number must be smaller
        than the segment size.`, true);

    // "Merge %"
    create_tooltip("#merge-threshold-tooltip-button", `The size of the last
        segment must be at least as large as the given percentage relative to
        other segment sizes. If the length of the last segment is below this
        threshold, it will be attached to the previous segment.`, true);

    // "Milestone"
    create_tooltip("#milestone-tooltip-button", `Split the document into
        segments at each appearance of the provided string. Child segments will not
        contain the Milestone delimiter.`);
}

/**
 * Initializes the walkthrough.
 */
function walkthrough(){

    let intro = introJs();
    intro.setOptions({steps: [
        {
            intro: `Welcome to the Cut page!`,
            position: "top",
        },
        {
            element: "#cut-mode-section",
            intro: `This is the Cut Mode section. Here you can specify how you
                would like to cut up your documents.`,
            position: "top",
        },
        {
            element: "#cut-settings-section",
            intro: `Based on your selection in the Cut Mode section, there are
                additional settings to fill out before you can initiate a
                cut.`,
            position: "top",
        },
        {
            element: "#preview-button",
            intro: `Similar to Scrub, you can preview your changes without
                saving them here.`,
            position: "top",
        },
        {
            element: "#apply-button",
            intro: `Unlike in Scrub, Apply works by creating new documents
                based on your cutting parameters. The original document is
                kept intact, but is deselected.`,
            position: "top",
        },
        {
            element: "#navbar-right",
            intro: `Once you're satisfied with your cut documents, you can
                move on to other pages in Prepare, Visualize, or Analyze.`,
            position: "bottom"
        },
        {
            intro: `This concludes the Cut walkthrough!`,
            position: "top",
        }
    ]});

    intro.start();
}
<|endoftext|>


<commit_before>
;(function() {
	var console = window.console = window.console || {};
	if (console._whistleConsole) {
		return;
	}
	console._whistleConsole = true;
	var JSON = window.JSON || patchJSON();
	function patchJSON() {
	    var JSON = {};
		var rx_one = /^[\],:{}\s]*$/,
	        rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
	        rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
	        rx_four = /(?:^|:|,)(?:\s*\[)+/g,
	        rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
	        rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

	    function f(n) {
	        return n < 10
	            ? '0' + n
	            : n;
	    }

	    function this_value() {
	        return this.valueOf();
	    }

	    if (typeof Date.prototype.toJSON !== 'function') {

	        Date.prototype.toJSON = function () {

	            return isFinite(this.valueOf())
	                ? this.getUTCFullYear() + '-' +
	                        f(this.getUTCMonth() + 1) + '-' +
	                        f(this.getUTCDate()) + 'T' +
	                        f(this.getUTCHours()) + ':' +
	                        f(this.getUTCMinutes()) + ':' +
	                        f(this.getUTCSeconds()) + 'Z'
	                : null;
	        };

	        Boolean.prototype.toJSON = this_value;
	        Number.prototype.toJSON = this_value;
	        String.prototype.toJSON = this_value;
	    }

	    var gap,
	        indent,
	        meta,
	        rep;

	    function quote(string) {

	        rx_escapable.lastIndex = 0;
	        return rx_escapable.test(string)
	            ? '"' + string.replace(rx_escapable, function (a) {
	                var c = meta[a];
	                return typeof c === 'string'
	                    ? c
	                    : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
	            }) + '"'
	            : '"' + string + '"';
	    }

	    function str(key, holder) {

	        var i,
	            k,
	            v,
	            length,
	            mind = gap,
	            partial,
	            value = holder[key];

	        if (value && typeof value === 'object' &&
	                typeof value.toJSON === 'function') {
	            value = value.toJSON(key);
	        }

	        if (typeof rep === 'function') {
	            value = rep.call(holder, key, value);
	        }

	        switch (typeof value) {
	        case 'string':
	            return quote(value);

	        case 'number':

	            return isFinite(value)
	                ? String(value)
	                : 'null';

	        case 'boolean':
	        case 'null':

	            return String(value);

	        case 'object':

	            if (!value) {
	                return 'null';
	            }

	            gap += indent;
	            partial = [];

	            if (Object.prototype.toString.apply(value) === '[object Array]') {

	                length = value.length;
	                for (i = 0; i < length; i += 1) {
	                    partial[i] = str(i, value) || 'null';
	                }

	                v = partial.length === 0
	                    ? '[]'
	                    : gap
	                        ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
	                        : '[' + partial.join(',') + ']';
	                gap = mind;
	                return v;
	            }

	            if (rep && typeof rep === 'object') {
	                length = rep.length;
	                for (i = 0; i < length; i += 1) {
	                    if (typeof rep[i] === 'string') {
	                        k = rep[i];
	                        v = str(k, value);
	                        if (v) {
	                            partial.push(quote(k) + (
	                                gap
	                                    ? ': '
	                                    : ':'
	                            ) + v);
	                        }
	                    }
	                }
	            } else {

	                for (k in value) {
	                    if (Object.prototype.hasOwnProperty.call(value, k)) {
	                        v = str(k, value);
	                        if (v) {
	                            partial.push(quote(k) + (
	                                gap
	                                    ? ': '
	                                    : ':'
	                            ) + v);
	                        }
	                    }
	                }
	            }

	            v = partial.length === 0
	                ? '{}'
	                : gap
	                    ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
	                    : '{' + partial.join(',') + '}';
	            gap = mind;
	            return v;
	        }
	    }

	    if (typeof JSON.stringify !== 'function') {
	        meta = {
	            '\b': '\\b',
	            '\t': '\\t',
	            '\n': '\\n',
	            '\f': '\\f',
	            '\r': '\\r',
	            '"': '\\"',
	            '\\': '\\\\'
	        };
	        JSON.stringify = function (value, replacer, space) {

	            var i;
	            gap = '';
	            indent = '';

	            if (typeof space === 'number') {
	                for (i = 0; i < space; i += 1) {
	                    indent += ' ';
	                }

	            } else if (typeof space === 'string') {
	                indent = space;
	            }

	            rep = replacer;
	            if (replacer && typeof replacer !== 'function' &&
	                    (typeof replacer !== 'object' ||
	                    typeof replacer.length !== 'number')) {
	                throw new Error('JSON.stringify');
	            }

	            return str('', {'': value});
	        };
	    }

	    return JSON;
	}

	function stringify(obj) {
		if (obj == null) {
			return '';
		}

		if (!obj) {
			return obj + '';
		}
		var type = typeof obj;
		if (type == 'string') {
			return obj;
		}

		if (obj instanceof Error) {
			return obj.stack || obj.message;
		}

		if (type == 'function') {
			return obj.toString();
		}

		return JSON.stringify(obj, null, '\t');
	}

	function addLog(level, text) {
		var img = new Image();
		var timer;
		img.src ='$LOG_CGI?level=' + level + '&text=' + encodeURIComponent(text);
		var preventGC = function() {
			img.onload = null;
			clearTimeout(timer);
		};
		img.onload = preventGC;
		timer = setTimeout(preventGC, 3000);
	}

	var levels = ['fatal', 'error', 'warn', 'info', 'debug', 'log'];
	var noop = function() {};
	for (var i = 0, len = levels.length; i < len; i++) {
		var level = levels[i];
		var fn = console[level] || noop;
		(function(level) {
			console[level] = function() {
				var result = [];
				for (var i = 0, len = arguments.length; i < len; i++) {
					result[i] = stringify(arguments[i]);
				}
				addLog(level, result.join(' '));
				fn.apply(this, arguments);
			};
		})(level);
	}

	window.onerror = function(message, filename, lineno, colno, error) {
		var pageInfo = '\r\nPage Url: ' + location.href + '\r\nUser Agent: ' + navigator.userAgent;
		if (error) {
			console.error((error.stack || error.message) + pageInfo);
		} else {
			console.error('Error: ' + message + '(' + filename
					+ ':' + lineno + ':' + (colno || 0) + ')' + pageInfo);
		}
	};

})();
<commit_msg>refactor: Add img.onerror<commit_after>
;(function() {
	var console = window.console = window.console || {};
	if (console._whistleConsole) {
		return;
	}
	console._whistleConsole = true;
	var JSON = window.JSON || patchJSON();
	function patchJSON() {
	    var JSON = {};
		var rx_one = /^[\],:{}\s]*$/,
	        rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
	        rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
	        rx_four = /(?:^|:|,)(?:\s*\[)+/g,
	        rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
	        rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

	    function f(n) {
	        return n < 10
	            ? '0' + n
	            : n;
	    }

	    function this_value() {
	        return this.valueOf();
	    }

	    if (typeof Date.prototype.toJSON !== 'function') {

	        Date.prototype.toJSON = function () {

	            return isFinite(this.valueOf())
	                ? this.getUTCFullYear() + '-' +
	                        f(this.getUTCMonth() + 1) + '-' +
	                        f(this.getUTCDate()) + 'T' +
	                        f(this.getUTCHours()) + ':' +
	                        f(this.getUTCMinutes()) + ':' +
	                        f(this.getUTCSeconds()) + 'Z'
	                : null;
	        };

	        Boolean.prototype.toJSON = this_value;
	        Number.prototype.toJSON = this_value;
	        String.prototype.toJSON = this_value;
	    }

	    var gap,
	        indent,
	        meta,
	        rep;

	    function quote(string) {

	        rx_escapable.lastIndex = 0;
	        return rx_escapable.test(string)
	            ? '"' + string.replace(rx_escapable, function (a) {
	                var c = meta[a];
	                return typeof c === 'string'
	                    ? c
	                    : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
	            }) + '"'
	            : '"' + string + '"';
	    }

	    function str(key, holder) {

	        var i,
	            k,
	            v,
	            length,
	            mind = gap,
	            partial,
	            value = holder[key];

	        if (value && typeof value === 'object' &&
	                typeof value.toJSON === 'function') {
	            value = value.toJSON(key);
	        }

	        if (typeof rep === 'function') {
	            value = rep.call(holder, key, value);
	        }

	        switch (typeof value) {
	        case 'string':
	            return quote(value);

	        case 'number':

	            return isFinite(value)
	                ? String(value)
	                : 'null';

	        case 'boolean':
	        case 'null':

	            return String(value);

	        case 'object':

	            if (!value) {
	                return 'null';
	            }

	            gap += indent;
	            partial = [];

	            if (Object.prototype.toString.apply(value) === '[object Array]') {

	                length = value.length;
	                for (i = 0; i < length; i += 1) {
	                    partial[i] = str(i, value) || 'null';
	                }

	                v = partial.length === 0
	                    ? '[]'
	                    : gap
	                        ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
	                        : '[' + partial.join(',') + ']';
	                gap = mind;
	                return v;
	            }

	            if (rep && typeof rep === 'object') {
	                length = rep.length;
	                for (i = 0; i < length; i += 1) {
	                    if (typeof rep[i] === 'string') {
	                        k = rep[i];
	                        v = str(k, value);
	                        if (v) {
	                            partial.push(quote(k) + (
	                                gap
	                                    ? ': '
	                                    : ':'
	                            ) + v);
	                        }
	                    }
	                }
	            } else {

	                for (k in value) {
	                    if (Object.prototype.hasOwnProperty.call(value, k)) {
	                        v = str(k, value);
	                        if (v) {
	                            partial.push(quote(k) + (
	                                gap
	                                    ? ': '
	                                    : ':'
	                            ) + v);
	                        }
	                    }
	                }
	            }

	            v = partial.length === 0
	                ? '{}'
	                : gap
	                    ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
	                    : '{' + partial.join(',') + '}';
	            gap = mind;
	            return v;
	        }
	    }

	    if (typeof JSON.stringify !== 'function') {
	        meta = {
	            '\b': '\\b',
	            '\t': '\\t',
	            '\n': '\\n',
	            '\f': '\\f',
	            '\r': '\\r',
	            '"': '\\"',
	            '\\': '\\\\'
	        };
	        JSON.stringify = function (value, replacer, space) {

	            var i;
	            gap = '';
	            indent = '';

	            if (typeof space === 'number') {
	                for (i = 0; i < space; i += 1) {
	                    indent += ' ';
	                }

	            } else if (typeof space === 'string') {
	                indent = space;
	            }

	            rep = replacer;
	            if (replacer && typeof replacer !== 'function' &&
	                    (typeof replacer !== 'object' ||
	                    typeof replacer.length !== 'number')) {
	                throw new Error('JSON.stringify');
	            }

	            return str('', {'': value});
	        };
	    }

	    return JSON;
	}

	function stringify(obj) {
		if (obj == null) {
			return '';
		}

		if (!obj) {
			return obj + '';
		}
		var type = typeof obj;
		if (type == 'string') {
			return obj;
		}

		if (obj instanceof Error) {
			return obj.stack || obj.message;
		}

		if (type == 'function') {
			return obj.toString();
		}

		return JSON.stringify(obj, null, '\t');
	}

	function addLog(level, text) {
		var img = new Image();
		var timer;
		img.src ='$LOG_CGI?level=' + level + '&text=' + encodeURIComponent(text);
		var preventGC = function() {
			img.onload = null;
			clearTimeout(timer);
		};
		img.onload = img.onerror = preventGC;
		timer = setTimeout(preventGC, 3000);
	}

	var levels = ['fatal', 'error', 'warn', 'info', 'debug', 'log'];
	var noop = function() {};
	for (var i = 0, len = levels.length; i < len; i++) {
		var level = levels[i];
		var fn = console[level] || noop;
		(function(level) {
			console[level] = function() {
				var result = [];
				for (var i = 0, len = arguments.length; i < len; i++) {
					result[i] = stringify(arguments[i]);
				}
				addLog(level, result.join(' '));
				fn.apply(this, arguments);
			};
		})(level);
	}

	window.onerror = function(message, filename, lineno, colno, error) {
		var pageInfo = '\r\nPage Url: ' + location.href + '\r\nUser Agent: ' + navigator.userAgent;
		if (error) {
			console.error((error.stack || error.message) + pageInfo);
		} else {
			console.error('Error: ' + message + '(' + filename
					+ ':' + lineno + ':' + (colno || 0) + ')' + pageInfo);
		}
	};

})();
<|endoftext|>


<commit_before>import { error } from '../../util';

const sqrt2 = Math.sqrt(2);

// Function which colapses 2 (meta) nodes into one
// Updates the remaining edge lists
// Receives as a paramater the edge which causes the collapse
const collapse = function( edgeIndex, nodeMap, remainingEdges ){
  if( remainingEdges.length === 0 ){
    error(`Karger-Stein must be run on a connected (sub)graph`);
  }

  let edgeInfo = remainingEdges[ edgeIndex ];
  let sourceIn = edgeInfo[1];
  let targetIn = edgeInfo[2];
  let partition1 = nodeMap[ sourceIn ];
  let partition2 = nodeMap[ targetIn ];
  let newEdges = remainingEdges; // re-use array

  // Delete all edges between partition1 and partition2
  for( let i = newEdges.length - 1; i >=0; i-- ){
    let edge = newEdges[i];
    let src = edge[1];
    let tgt = edge[2];

    if(
      ( nodeMap[ src ] === partition1 && nodeMap[ tgt ] === partition2 ) ||
      ( nodeMap[ src ] === partition2 && nodeMap[ tgt ] === partition1 )
    ){
      newEdges.splice(i, 1);
    }
  }

  // All edges pointing to partition2 should now point to partition1
  for( let i = 0; i < newEdges.length; i++ ){
    let edge = newEdges[i];

    if( edge[1] === partition2 ){ // Check source
      newEdges[i] = edge.slice(); // copy
      newEdges[i][1] = partition1;
    } else if( edge[2] === partition2 ){ // Check target
      newEdges[i] = edge.slice(); // copy
      newEdges[i][2] = partition1;
    }
  }

  // Move all nodes from partition2 to partition1
  for( let i = 0; i < nodeMap.length; i++ ){
    if( nodeMap[i] === partition2 ){
      nodeMap[i] = partition1;
    }
  }

  return newEdges;
};

// Contracts a graph until we reach a certain number of meta nodes
const contractUntil = function( metaNodeMap, remainingEdges, size, sizeLimit ){
  while( size > sizeLimit ){
    // Choose an edge randomly
    let edgeIndex = Math.floor( (Math.random() * remainingEdges.length) );

    // Collapse graph based on edge
    remainingEdges = collapse( edgeIndex, metaNodeMap, remainingEdges );

    size--;
  }

  return remainingEdges;
};

const elesfn = ({

  // Computes the minimum cut of an undirected graph
  // Returns the correct answer with high probability
  kargerStein: function(){
    let { nodes, edges } = this.byGroup();
    edges.unmergeBy(edge => edge.isLoop());

    let numNodes = nodes.length;
    let numEdges = edges.length;
    let numIter = Math.ceil( Math.pow( Math.log( numNodes ) / Math.LN2, 2 ) );
    let stopSize = Math.floor( numNodes / sqrt2 );

    if( numNodes < 2 ){
      error( 'At least 2 nodes are required for Karger-Stein algorithm' );
      return undefined;
    }

    // Now store edge destination as indexes
    // Format for each edge (edge index, source node index, target node index)
    let edgeIndexes = [];
    for( let i = 0; i < numEdges; i++ ){
      let e = edges[ i ];
      edgeIndexes.push([ i, nodes.indexOf(e.source()), nodes.indexOf(e.target()) ]);
    }

    // We will store the best cut found here
    let minCutSize = Infinity;
    let minCutEdgeIndexes = [];
    let minCutNodeMap = new Array(numNodes);

    // Initial meta node partition
    let metaNodeMap = new Array(numNodes);
    let metaNodeMap2 = new Array(numNodes);

    let copyNodesMap = (from, to) => {
      for( let i = 0; i < numNodes; i++ ){
        to[i] = from[i];
      }
    };

    // Main loop
    for( let iter = 0; iter <= numIter; iter++ ){
      // Reset meta node partition
      for( let i = 0; i < numNodes; i++ ){ metaNodeMap[i] = i; }

      // Contract until stop point (stopSize nodes)
      let edgesState = contractUntil( metaNodeMap, edgeIndexes.slice(), numNodes, stopSize );
      let edgesState2 = edgesState.slice(); // copy

      // Create a copy of the colapsed nodes state
      copyNodesMap(metaNodeMap, metaNodeMap2);

      // Run 2 iterations starting in the stop state
      let res1 = contractUntil( metaNodeMap, edgesState, stopSize, 2 );
      let res2 = contractUntil( metaNodeMap2, edgesState2, stopSize, 2 );

      // Is any of the 2 results the best cut so far?
      if( res1.length <= res2.length && res1.length < minCutSize ){
        minCutSize = res1.length;
        minCutEdgeIndexes = res1;
        copyNodesMap(metaNodeMap, minCutNodeMap);
      } else if( res2.length <= res1.length && res2.length < minCutSize ){
        minCutSize = res2.length;
        minCutEdgeIndexes = res2;
        copyNodesMap(metaNodeMap2, minCutNodeMap);
      }
    } // end of main loop

    // Construct result
    let cut = this.spawn( minCutEdgeIndexes.map(e => edges[e[0]]) );
    let partition1 = this.spawn();
    let partition2 = this.spawn();

    // traverse metaNodeMap for best cut
    let witnessNodePartition = minCutNodeMap[0];
    for( let i = 0; i < minCutNodeMap.length; i++ ){
      let partitionId = minCutNodeMap[i];
      let node = nodes[i];

      if( partitionId === witnessNodePartition ){
        partition1.merge( node );
      } else {
        partition2.merge( node );
      }
    }

    // construct components corresponding to each disjoint subset of nodes
    const constructComponent = (subset) => {
      const component = this.spawn();

      subset.forEach(node => {
        component.merge(node);

        node.connectedEdges().forEach(edge => {
          // ensure edge is within calling collection and edge is not in cut
          if (this.contains(edge) && !cut.contains(edge)) {
            component.merge(edge);
          }
        });
      });

      return component;
    };

    const components = [
      constructComponent(partition1),
      constructComponent(partition2)
    ];

    let ret = {
      cut,
      components
    };

    return ret;
  }
}); // elesfn

export default elesfn;
<commit_msg>Allow compatibility with the old `partition1`-`partition2` API for Karger-Stein<commit_after>import { error } from '../../util';

const sqrt2 = Math.sqrt(2);

// Function which colapses 2 (meta) nodes into one
// Updates the remaining edge lists
// Receives as a paramater the edge which causes the collapse
const collapse = function( edgeIndex, nodeMap, remainingEdges ){
  if( remainingEdges.length === 0 ){
    error(`Karger-Stein must be run on a connected (sub)graph`);
  }

  let edgeInfo = remainingEdges[ edgeIndex ];
  let sourceIn = edgeInfo[1];
  let targetIn = edgeInfo[2];
  let partition1 = nodeMap[ sourceIn ];
  let partition2 = nodeMap[ targetIn ];
  let newEdges = remainingEdges; // re-use array

  // Delete all edges between partition1 and partition2
  for( let i = newEdges.length - 1; i >=0; i-- ){
    let edge = newEdges[i];
    let src = edge[1];
    let tgt = edge[2];

    if(
      ( nodeMap[ src ] === partition1 && nodeMap[ tgt ] === partition2 ) ||
      ( nodeMap[ src ] === partition2 && nodeMap[ tgt ] === partition1 )
    ){
      newEdges.splice(i, 1);
    }
  }

  // All edges pointing to partition2 should now point to partition1
  for( let i = 0; i < newEdges.length; i++ ){
    let edge = newEdges[i];

    if( edge[1] === partition2 ){ // Check source
      newEdges[i] = edge.slice(); // copy
      newEdges[i][1] = partition1;
    } else if( edge[2] === partition2 ){ // Check target
      newEdges[i] = edge.slice(); // copy
      newEdges[i][2] = partition1;
    }
  }

  // Move all nodes from partition2 to partition1
  for( let i = 0; i < nodeMap.length; i++ ){
    if( nodeMap[i] === partition2 ){
      nodeMap[i] = partition1;
    }
  }

  return newEdges;
};

// Contracts a graph until we reach a certain number of meta nodes
const contractUntil = function( metaNodeMap, remainingEdges, size, sizeLimit ){
  while( size > sizeLimit ){
    // Choose an edge randomly
    let edgeIndex = Math.floor( (Math.random() * remainingEdges.length) );

    // Collapse graph based on edge
    remainingEdges = collapse( edgeIndex, metaNodeMap, remainingEdges );

    size--;
  }

  return remainingEdges;
};

const elesfn = ({

  // Computes the minimum cut of an undirected graph
  // Returns the correct answer with high probability
  kargerStein: function(){
    let { nodes, edges } = this.byGroup();
    edges.unmergeBy(edge => edge.isLoop());

    let numNodes = nodes.length;
    let numEdges = edges.length;
    let numIter = Math.ceil( Math.pow( Math.log( numNodes ) / Math.LN2, 2 ) );
    let stopSize = Math.floor( numNodes / sqrt2 );

    if( numNodes < 2 ){
      error( 'At least 2 nodes are required for Karger-Stein algorithm' );
      return undefined;
    }

    // Now store edge destination as indexes
    // Format for each edge (edge index, source node index, target node index)
    let edgeIndexes = [];
    for( let i = 0; i < numEdges; i++ ){
      let e = edges[ i ];
      edgeIndexes.push([ i, nodes.indexOf(e.source()), nodes.indexOf(e.target()) ]);
    }

    // We will store the best cut found here
    let minCutSize = Infinity;
    let minCutEdgeIndexes = [];
    let minCutNodeMap = new Array(numNodes);

    // Initial meta node partition
    let metaNodeMap = new Array(numNodes);
    let metaNodeMap2 = new Array(numNodes);

    let copyNodesMap = (from, to) => {
      for( let i = 0; i < numNodes; i++ ){
        to[i] = from[i];
      }
    };

    // Main loop
    for( let iter = 0; iter <= numIter; iter++ ){
      // Reset meta node partition
      for( let i = 0; i < numNodes; i++ ){ metaNodeMap[i] = i; }

      // Contract until stop point (stopSize nodes)
      let edgesState = contractUntil( metaNodeMap, edgeIndexes.slice(), numNodes, stopSize );
      let edgesState2 = edgesState.slice(); // copy

      // Create a copy of the colapsed nodes state
      copyNodesMap(metaNodeMap, metaNodeMap2);

      // Run 2 iterations starting in the stop state
      let res1 = contractUntil( metaNodeMap, edgesState, stopSize, 2 );
      let res2 = contractUntil( metaNodeMap2, edgesState2, stopSize, 2 );

      // Is any of the 2 results the best cut so far?
      if( res1.length <= res2.length && res1.length < minCutSize ){
        minCutSize = res1.length;
        minCutEdgeIndexes = res1;
        copyNodesMap(metaNodeMap, minCutNodeMap);
      } else if( res2.length <= res1.length && res2.length < minCutSize ){
        minCutSize = res2.length;
        minCutEdgeIndexes = res2;
        copyNodesMap(metaNodeMap2, minCutNodeMap);
      }
    } // end of main loop

    // Construct result
    let cut = this.spawn( minCutEdgeIndexes.map(e => edges[e[0]]) );
    let partition1 = this.spawn();
    let partition2 = this.spawn();

    // traverse metaNodeMap for best cut
    let witnessNodePartition = minCutNodeMap[0];
    for( let i = 0; i < minCutNodeMap.length; i++ ){
      let partitionId = minCutNodeMap[i];
      let node = nodes[i];

      if( partitionId === witnessNodePartition ){
        partition1.merge( node );
      } else {
        partition2.merge( node );
      }
    }

    // construct components corresponding to each disjoint subset of nodes
    const constructComponent = (subset) => {
      const component = this.spawn();

      subset.forEach(node => {
        component.merge(node);

        node.connectedEdges().forEach(edge => {
          // ensure edge is within calling collection and edge is not in cut
          if (this.contains(edge) && !cut.contains(edge)) {
            component.merge(edge);
          }
        });
      });

      return component;
    };

    const components = [
      constructComponent(partition1),
      constructComponent(partition2)
    ];

    let ret = {
      cut,
      components,

      // n.b. partitions are included to be compatible with the old api spec
      // (could be removed in a future major version)
      partition1,
      partition2
    };

    return ret;
  }
}); // elesfn

export default elesfn;
<|endoftext|>


<commit_before>/*
   Provide the XMLHttpRequest constructor for IE 5.x-6.x:
   Other browsers (including IE 7.x-8.x) do not redefine
   XMLHttpRequest if it already exists.

   This example is based on findings at:
   http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
*/
if (typeof XMLHttpRequest == "undefined")
  XMLHttpRequest = function () {
    try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
      catch (e) {}
    try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
      catch (e) {}
    try { return new ActiveXObject("Msxml2.XMLHTTP"); }
      catch (e) {}
    //Microsoft.XMLHTTP points to Msxml2.XMLHTTP.3.0 and is redundant
    throw new Error("This browser does not support XMLHttpRequest.");
  };

var IDE_clone = function(object) {
  var newObj = (object instanceof Array) ? [] : {};
  for (var i in object) {
    if (i == 'clone') continue;
    if (object[i] && typeof object[i] == "object") {
      newObj[i] = IDE_clone(object[i]);
    } else newObj[i] = object[i]
  } return newObj;
};

var IDE_base = "control.php";
var IDE_async_count = 0;
var IDE_backend_debug = null;
showElement = hideElement = function(){};

IDE_notification_callback = function(note) {
	var object = createDOM('span');
	object.innerHTML = note + ' [dismiss]';
	var message = status_rich_show(object, LEVEL_WARN);
	setTimeout(message.close, 10000);
};

function IDE_backend_request(command, args, successCallback, errorCallback) {
	var rq = JSON.stringify(args);
	var xhr = new XMLHttpRequest();
	var cb = function() {
		if (xhr.readyState != 4) return;
		IDE_async_count--;
		if( IDE_async_count == 0 ) {
			hideElement('rotating-box');
		}
		if (xhr.status == 200) {
			if (xhr.getResponseHeader("Content-type") == "text/html") {
				// PHP fatal error
				errorCallback(-1, "fatal PHP error", args);
				return;
			}
			var rt = xhr.responseText;
			var rp = JSON.parse(rt);
			if (rp.debug) {
				IDE_backend_debug = rp.debug;
			}
			if (rp.notifications) {
				forEach(rp.notifications, IDE_notification_callback);
			}
			if (rp.error) {
				errorCallback(rp.error[0], rp.error[1], args);
			} else {
				successCallback(rp, args);
			}
		} else {
			errorCallback(-xhr.status, xhr.statusText, args);
		}
	};
	xhr.open("POST", IDE_base + "/" + command, true);
	xhr.onreadystatechange = cb;
	xhr.setRequestHeader("Content-type", "text/json");
	showElement('rotating-box');
	IDE_async_count++;
	xhr.send(rq);
}

/// Shrink a (git) hashes to a common and more size for display
function IDE_hash_shrink(hash) {
	var hash_length = 9;
	if(hash == null) {
		return false;
	}
	if(hash.length < hash_length) {
		return hash;
	}
	return hash.substring(0, hash_length);
}

/// Compare (git) hashes of potentially unequal length
function IDE_hash_compare(a, b) {
	var min_hash_length = 6;
	if(a.length < min_hash_length || b.length < min_hash_length) {
		return false;
	}
	if(a == b) {
		return true;
	}
	var min_len = Math.min(a.length, b.length);
	var short_a = a.substring(0, min_len);
	var short_b = b.substring(0, min_len);
	return (short_a == short_b)
}

function IDE_path_get_project(path) {
	// index of '/' starting from char 1 onwards
	var idx = path.indexOf('/', 1);
	if(idx < 0) {
		return path;
	}
	// return a substring to that point
	return path.substring(1,idx);
}

function IDE_path_get_file(path) {
	// index of '/' starting from char 1 onwards
	var idx = path.indexOf('/', 1);
	if(idx < 0) {
		return path;
	}
	// return a substring from that point
	return path.substring(idx+1);
}

/// Have they got java enabled?
function IDE_java_enabled() {
	return navigator.javaEnabled();
}
<commit_msg>Removed the timeout from notifications.<commit_after>/*
   Provide the XMLHttpRequest constructor for IE 5.x-6.x:
   Other browsers (including IE 7.x-8.x) do not redefine
   XMLHttpRequest if it already exists.

   This example is based on findings at:
   http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
*/
if (typeof XMLHttpRequest == "undefined")
  XMLHttpRequest = function () {
    try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
      catch (e) {}
    try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
      catch (e) {}
    try { return new ActiveXObject("Msxml2.XMLHTTP"); }
      catch (e) {}
    //Microsoft.XMLHTTP points to Msxml2.XMLHTTP.3.0 and is redundant
    throw new Error("This browser does not support XMLHttpRequest.");
  };

var IDE_clone = function(object) {
  var newObj = (object instanceof Array) ? [] : {};
  for (var i in object) {
    if (i == 'clone') continue;
    if (object[i] && typeof object[i] == "object") {
      newObj[i] = IDE_clone(object[i]);
    } else newObj[i] = object[i]
  } return newObj;
};

var IDE_base = "control.php";
var IDE_async_count = 0;
var IDE_backend_debug = null;
showElement = hideElement = function(){};

IDE_notification_callback = function(note) {
	var object = createDOM('span');
	object.innerHTML = note + ' [dismiss]';
	status_rich_show(object, LEVEL_WARN);
};

function IDE_backend_request(command, args, successCallback, errorCallback) {
	var rq = JSON.stringify(args);
	var xhr = new XMLHttpRequest();
	var cb = function() {
		if (xhr.readyState != 4) return;
		IDE_async_count--;
		if( IDE_async_count == 0 ) {
			hideElement('rotating-box');
		}
		if (xhr.status == 200) {
			if (xhr.getResponseHeader("Content-type") == "text/html") {
				// PHP fatal error
				errorCallback(-1, "fatal PHP error", args);
				return;
			}
			var rt = xhr.responseText;
			var rp = JSON.parse(rt);
			if (rp.debug) {
				IDE_backend_debug = rp.debug;
			}
			if (rp.notifications) {
				forEach(rp.notifications, IDE_notification_callback);
			}
			if (rp.error) {
				errorCallback(rp.error[0], rp.error[1], args);
			} else {
				successCallback(rp, args);
			}
		} else {
			errorCallback(-xhr.status, xhr.statusText, args);
		}
	};
	xhr.open("POST", IDE_base + "/" + command, true);
	xhr.onreadystatechange = cb;
	xhr.setRequestHeader("Content-type", "text/json");
	showElement('rotating-box');
	IDE_async_count++;
	xhr.send(rq);
}

/// Shrink a (git) hashes to a common and more size for display
function IDE_hash_shrink(hash) {
	var hash_length = 9;
	if(hash == null) {
		return false;
	}
	if(hash.length < hash_length) {
		return hash;
	}
	return hash.substring(0, hash_length);
}

/// Compare (git) hashes of potentially unequal length
function IDE_hash_compare(a, b) {
	var min_hash_length = 6;
	if(a.length < min_hash_length || b.length < min_hash_length) {
		return false;
	}
	if(a == b) {
		return true;
	}
	var min_len = Math.min(a.length, b.length);
	var short_a = a.substring(0, min_len);
	var short_b = b.substring(0, min_len);
	return (short_a == short_b)
}

function IDE_path_get_project(path) {
	// index of '/' starting from char 1 onwards
	var idx = path.indexOf('/', 1);
	if(idx < 0) {
		return path;
	}
	// return a substring to that point
	return path.substring(1,idx);
}

function IDE_path_get_file(path) {
	// index of '/' starting from char 1 onwards
	var idx = path.indexOf('/', 1);
	if(idx < 0) {
		return path;
	}
	// return a substring from that point
	return path.substring(idx+1);
}

/// Have they got java enabled?
function IDE_java_enabled() {
	return navigator.javaEnabled();
}
<|endoftext|>


<commit_before>const way = require('senseway');
const mcbsp = require('mcbsp');
const renderWay = require('./renderWay');

module.exports = (model, dispatch) => {
  const container = document.createElement('div');
  const channelMeans = way.mean(model.history);
  const channelGain = way.map(channelMeans, mcbsp.gain);

  container.appendChild(renderWay(channelMeans, 'a priori'));
  container.appendChild(renderWay(channelGain, 'infogain'));

  return container;
};
<commit_msg>Rename infogain label to entropy<commit_after>const way = require('senseway');
const mcbsp = require('mcbsp');
const renderWay = require('./renderWay');

module.exports = (model, dispatch) => {
  const container = document.createElement('div');
  const channelMeans = way.mean(model.history);
  const channelGain = way.map(channelMeans, mcbsp.gain);

  container.appendChild(renderWay(channelMeans, 'a priori'));
  container.appendChild(renderWay(channelGain, 'entropy'));

  return container;
};
<|endoftext|>


<commit_before>/*
Copyright (c) 2013, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
var path = require('path'),
    exec = require('child_process').spawn;

module.exports = function(grunt) {
    var start,
        VERSION,
        historyName = "HISTORY.md",
              token = /@VERSION@/gi,
          noChanges = /No changes./,
                key = "\n3.";

    grunt.registerTask('history-rollup', 'Create the history rollup file.', function(){

        var output = '',
        rollupName = "HISTORYROLLUP.md",
         fileCount = 0,
        destination;

        start = path.join(process.cwd(), 'src');
        destination = path.join(process.cwd(), rollupName);
        VERSION = grunt.config.get('version');

        grunt.log.writeln("History Rollup Creation starting...");
        grunt.log.writeln("Starting in: "+start);

        grunt.file.recurse(start, function(abspath,rootdir,subdir,filename){
            if(filename === historyName){
                var content = grunt.file.read(abspath);
                content = content.split(key)[0];
                //grunt.log.writeln(content);

                if(content && content.search(token) && content.search(noChanges) == -1){
                    grunt.log.writeln("Found content in " + abspath);
                    grunt.log.writeln(">>> adding to buffer");
                    output += "\n" +content;
                    fileCount++;
                }
            }

        });

        // report findings
        grunt.log.writeln("Finished scanning files.");
        grunt.log.writeln("Added "+ fileCount + " entries.");

        // done recursing now write to file
        if(output !== ""){
            grunt.file.write(destination, output);
            grunt.log.writeln("Wrote to file: " + destination);
        }

    });

    grunt.registerTask('history-populate', 'Populate history files with @VERSION@ if not there already.', function (){
        var nochanges = "\n@VERSION@\n------\n\n* No changes.\n",
            fileCount = 0,
            content,
            newContent,
            contArr;

        start = path.join(process.cwd(), 'src');

        grunt.log.writeln("History Populate starting...");

        grunt.file.recurse(start, function(abspath,rootdir,subdir,filename){
            if(filename === historyName){
                content = grunt.file.read(abspath);

                if(content.match(token) !== null){
                    grunt.log.writeln("Found a @VERSION@ in " + abspath + " skipping...");
                } else {
                    grunt.log.writeln("No @VERSION@ found. Adding to : " + abspath);
                    contArr = content.split(key);
                    grunt.log.writeln(contArr.length);
                    contArr[0] = contArr[0] + nochanges; // add new history entry.
                    newContent = contArr.join(key);
                    grunt.file.write(abspath, newContent); //overwrite old HISTORY.md
                    fileCount++;
                }
            }
        });

        grunt.log.writeln("History Populate done. Files changed: "+ fileCount);

    });

    grunt.registerTask('history-replace', 'Replace @VERSION@ with current release version.', function(){
        var fileCount = 0;

        start = path.join(process.cwd(), 'src');
        VERSION = grunt.config.get('version');

        grunt.log.writeln("History Version Replace starting...");
        grunt.log.writeln("Using release version: " + VERSION);

        grunt.file.recurse(start, function(abspath,rootdir,subdir,filename){
            if(filename === historyName){
                var content = grunt.file.read(abspath),
                    newContent,
                    contentMatch = content.match(token);

                if(contentMatch){
                    if(contentMatch.length == 1){
                        grunt.log.writeln("Found exactly 1 @VERSION@ in " + abspath);

                        newContent = content.replace(token,VERSION);
                        grunt.file.write(abspath, newContent); //overwrite old HISTORY.md
                        grunt.log.writeln("Wrote " + VERSION + " to " + abspath);
                        fileCount++;

                    } else {
                        grunt.log.error("Found " + contentMatch.length + " @VERSION@'s in " + abspath + " skipping...");
                    }

                } else {
                    grunt.log.error("Found 0 @VERSION@'s in " + abspath + " skipping...");
                }
            }
        });

        grunt.log.writeln("History Version Replace done. Files changed: "+ fileCount);

    });

};<commit_msg>newline at eof<commit_after>/*
Copyright (c) 2013, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://yuilibrary.com/license/
*/
var path = require('path'),
    exec = require('child_process').spawn;

module.exports = function(grunt) {
    var start,
        VERSION,
        historyName = "HISTORY.md",
              token = /@VERSION@/gi,
          noChanges = /No changes./,
                key = "\n3.";

    grunt.registerTask('history-rollup', 'Create the history rollup file.', function(){

        var output = '',
        rollupName = "HISTORYROLLUP.md",
         fileCount = 0,
        destination;

        start = path.join(process.cwd(), 'src');
        destination = path.join(process.cwd(), rollupName);
        VERSION = grunt.config.get('version');

        grunt.log.writeln("History Rollup Creation starting...");
        grunt.log.writeln("Starting in: "+start);

        grunt.file.recurse(start, function(abspath,rootdir,subdir,filename){
            if(filename === historyName){
                var content = grunt.file.read(abspath);
                content = content.split(key)[0];
                //grunt.log.writeln(content);

                if(content && content.search(token) && content.search(noChanges) == -1){
                    grunt.log.writeln("Found content in " + abspath);
                    grunt.log.writeln(">>> adding to buffer");
                    output += "\n" +content;
                    fileCount++;
                }
            }

        });

        // report findings
        grunt.log.writeln("Finished scanning files.");
        grunt.log.writeln("Added "+ fileCount + " entries.");

        // done recursing now write to file
        if(output !== ""){
            grunt.file.write(destination, output);
            grunt.log.writeln("Wrote to file: " + destination);
        }

    });

    grunt.registerTask('history-populate', 'Populate history files with @VERSION@ if not there already.', function (){
        var nochanges = "\n@VERSION@\n------\n\n* No changes.\n",
            fileCount = 0,
            content,
            newContent,
            contArr;

        start = path.join(process.cwd(), 'src');

        grunt.log.writeln("History Populate starting...");

        grunt.file.recurse(start, function(abspath,rootdir,subdir,filename){
            if(filename === historyName){
                content = grunt.file.read(abspath);

                if(content.match(token) !== null){
                    grunt.log.writeln("Found a @VERSION@ in " + abspath + " skipping...");
                } else {
                    grunt.log.writeln("No @VERSION@ found. Adding to : " + abspath);
                    contArr = content.split(key);
                    grunt.log.writeln(contArr.length);
                    contArr[0] = contArr[0] + nochanges; // add new history entry.
                    newContent = contArr.join(key);
                    grunt.file.write(abspath, newContent); //overwrite old HISTORY.md
                    fileCount++;
                }
            }
        });

        grunt.log.writeln("History Populate done. Files changed: "+ fileCount);

    });

    grunt.registerTask('history-replace', 'Replace @VERSION@ with current release version.', function(){
        var fileCount = 0;

        start = path.join(process.cwd(), 'src');
        VERSION = grunt.config.get('version');

        grunt.log.writeln("History Version Replace starting...");
        grunt.log.writeln("Using release version: " + VERSION);

        grunt.file.recurse(start, function(abspath,rootdir,subdir,filename){
            if(filename === historyName){
                var content = grunt.file.read(abspath),
                    newContent,
                    contentMatch = content.match(token);

                if(contentMatch){
                    if(contentMatch.length == 1){
                        grunt.log.writeln("Found exactly 1 @VERSION@ in " + abspath);

                        newContent = content.replace(token,VERSION);
                        grunt.file.write(abspath, newContent); //overwrite old HISTORY.md
                        grunt.log.writeln("Wrote " + VERSION + " to " + abspath);
                        fileCount++;

                    } else {
                        grunt.log.error("Found " + contentMatch.length + " @VERSION@'s in " + abspath + " skipping...");
                    }

                } else {
                    grunt.log.error("Found 0 @VERSION@'s in " + abspath + " skipping...");
                }
            }
        });

        grunt.log.writeln("History Version Replace done. Files changed: "+ fileCount);

    });

};

<|endoftext|>