<commit_before>(function(){

    // "Globals"
    var Scene = wireframe.engine.Scene;
    var scene = new Scene({canvas_id: 'canvas', width:600, height:400});
    var mesh;
    var current_audio;
    var ROWS = 20;
    var COLS = 16;

    (function initializeScene(){
        /************************
        ***  Wireframe setup  ***
        *************************/
        var Mesh = wireframe.geometry.Mesh;
        var vertices = [];
        var faces = [];

        // Build mesh vertices
        for (var row = 0; row < ROWS; row++){
            for (var col = 0; col < COLS; col++){
                vertices.push([(col*20)-160, 0, (row*(-20))]);
            }
        }

        // Build mesh edges.
        for (var row = 0; row < ROWS-1; row++){
            for (var col = 0; col < COLS-1; col++){
                var a = col + (row * COLS);
                var b = (col + 1) + (row * COLS);
                var d = (col +1)+ ((row+1) * COLS);
                var c = col + ((row +1)* COLS);
                faces.push({"face": [a, c, d], "color": "green"});
                faces.push({"face": [a, d, b], "color": "green"});
            }
        }
        mesh = Mesh.fromJSON({
            "name": "vu",
            "vertices": vertices,
            "faces": faces
        });

        scene.camera.moveTo(0, -200, 400);
        scene.camera.lookDown(0.2);
        scene.addMesh(mesh);

        function moveCamera(e){
            if (scene.isKeyDown('w')) {
                scene.camera.moveForward(3);
            }
            if (scene.isKeyDown('s')) {
                scene.camera.moveBackward(3);
            }
            if (scene.isKeyDown('a')) {
                scene.camera.moveLeft(3);
            }
            if (scene.isKeyDown('d')) {
                scene.camera.moveRight(3);
            }
            if (scene.isKeyDown('r')) {
                scene.camera.moveUp(3);
            }
            if (scene.isKeyDown('f')) {
                scene.camera.moveDown(3);
            }
            if (scene.isKeyDown('t')) {
                scene.camera.lookUp(0.02);
            }
            if (scene.isKeyDown('g')) {
                scene.camera.lookDown(0.02);
            }
            if (scene.isKeyDown('q')) {
                scene.camera.turnLeft(0.02);
            }
            if (scene.isKeyDown('e')) {
                scene.camera.turnRight(0.02);
            }
        }

        scene.addListener('keydown', moveCamera);
        scene.toggleBackfaceCulling();
    })();

    (function initializeAudio(){
        /************************
        ***     DOM setup     ***
        *************************/
        var canvas = document.getElementById('canvas');

        // ready indicates whether audio is loaded and ready to be played.
        var ready = document.createElement('div');
        ready.appendChild(document.createTextNode(""));
        var start_button = document.createElement('button');
        start_button.style.marginLeft = "10px";
        start_button.appendChild(document.createTextNode("Start"));
        ready.appendChild(start_button);
        ready.loading = function(){
            this.childNodes[0].textContent = "Audio loading...";
            this.style.color = 'red';
            this.childNodes[1].disabled = true;
        };
        ready.ready = function(){
            this.childNodes[0].textContent = "Ready!";
            this.style.color = 'green';
            this.childNodes[1].disabled = false;
        };
        ready.error = function(){
            this.childNodes[0].textContent = "Error! File type not supported";
            this.style.color = 'red';
            this.childNodes[1].disabled = true;
        };
        ready.loading();
        if (canvas.nextSibling) {
          canvas.parentNode.insertBefore(ready, canvas.nextSibling);
        }
        else {
          canvas.parentNode.appendChild(ready);
        }

        /************************
        ***    Audio setup    ***
        *************************/

        var audioctx = new (window.AudioContext || window.webkitAudioContext)();
        var analyser = audioctx.createAnalyser();
        analyser.fftSize = 64;

        var dataArray = new Uint8Array(analyser.frequencyBinCount);
        var audio_node, javascript_node;
        // clicklistener function needs to be held onto so that the event
        // listener can be removed, when necessary.
        var clicklistener;
        var playing = false;

        function initAudio() {
            javascript_node = audioctx.createScriptProcessor(2048, 1, 1);
            javascript_node.connect(audioctx.destination);

            audio_node = audioctx.createBufferSource();
            audio_node.connect(analyser);
            analyser.connect(javascript_node);

            audio_node.connect(audioctx.destination);
        }

        function decodeAudio(buffer){
            audioctx.decodeAudioData(buffer, function(buffer) {
                // Remove clicklistener to avoid adding multiple
                // event listeners
                start_button.removeEventListener('click', clicklistener);
                soundReady(buffer);
            }, onError);
        }

        function XHRLoadSound(url) {
            var request = new XMLHttpRequest();
            request.open('GET', url, true);
            request.responseType = 'arraybuffer';
            request.onload = function() {
                current_audio = request.response;
                decodeAudio(request.response);
            };
            request.send();
        }

        // Keep track of where in the audio track we are.
        var playtime = 0;
        var time_started;
        function playAudio(){
            playing = true;
            time_started = new Date();
            audio_node.start(0, playtime);
        }
        function pauseAudio(){
            // Convert times from miliseconds to seconds
            playtime = playtime + ((new Date() - time_started)/1000);
            playing = false;
            audio_node.stop();
            // Since buffersource is one-time use, we need
            // to reinitialize if we want to play again after pausing
            initAudio();
            decodeAudio();
        }

        function soundReady(buffer){
            ready.ready();
            clicklistener = function(e){
                if (playing){
                    this.textContent = "Start";
                    pauseAudio();
                } else {
                    this.textContent = "Stop";
                    audio_node.buffer = buffer;
                    playAudio();
                }
            };
            start_button.addEventListener('click', clicklistener);
        }

        function onError(e) {
            ready.error();
        }

        function fileDrop(e){
            e.preventDefault();
            playtime = 0;
            ready.loading();
            var files = e.dataTransfer.files;
            var reader = new FileReader();

            reader.onload = function(e) {
                current_audio = e.target.result;
                decodeAudio(e.target.result);
            };
            reader.readAsArrayBuffer(files[0]);

        }

        // Required for drag 'n' drop to work on canvas
        canvas.addEventListener("dragover", function (e) {
            e.preventDefault();
        }, false);
        canvas.addEventListener('drop', fileDrop);

        function draw(array) {
            var current_time = new Date();
            // Shift everything back one row.
            if (current_time - last_update > 100){
                // Take rows from back to front,
                // otherwise we would overwrite rows we haven't copied over yet.
                for (var row = ROWS - 1; row >= 1; row--){
                    for (var col = 0; col < COLS; col++){
                        var i = col + ((row - 1) * COLS);
                        var i2 = col + (row * COLS);
                        mesh.vertices[i2].y = mesh.vertices[i].y;
                    }
                }
                last_update = current_time;
            }

            var barHeight;
            for(var i = 0; i < COLS; i++) {
                barHeight = array[i]/2;
                mesh.vertices[i].y = -barHeight;
            }

            scene.renderScene();
        }

        var last_update = new Date();
        function update(){
            analyser.getByteFrequencyData(dataArray);

            draw(dataArray);
            window.requestAnimationFrame(update);
        }

        // Start off with default audio file.
        initAudio();
        XHRLoadSound("../../audio/piano-sonata-no13.ogg");
        window.requestAnimationFrame(update);
    })();

})();<commit_msg>Fix VU pause behavior<commit_after>(function(){

    // "Globals"
    var Scene = wireframe.engine.Scene;
    var scene = new Scene({canvas_id: 'canvas', width:600, height:400});
    var mesh;
    var current_audio;
    var ROWS = 20;
    var COLS = 16;

    (function initializeScene(){
        /************************
        ***  Wireframe setup  ***
        *************************/
        var Mesh = wireframe.geometry.Mesh;
        var vertices = [];
        var faces = [];

        // Build mesh vertices
        for (var row = 0; row < ROWS; row++){
            for (var col = 0; col < COLS; col++){
                vertices.push([(col*20)-160, 0, (row*(-20))]);
            }
        }

        // Build mesh edges.
        for (var row = 0; row < ROWS-1; row++){
            for (var col = 0; col < COLS-1; col++){
                var a = col + (row * COLS);
                var b = (col + 1) + (row * COLS);
                var d = (col +1)+ ((row+1) * COLS);
                var c = col + ((row +1)* COLS);
                faces.push({"face": [a, c, d], "color": "green"});
                faces.push({"face": [a, d, b], "color": "green"});
            }
        }
        mesh = Mesh.fromJSON({
            "name": "vu",
            "vertices": vertices,
            "faces": faces
        });

        scene.camera.moveTo(0, -200, 400);
        scene.camera.lookDown(0.2);
        scene.addMesh(mesh);

        function moveCamera(e){
            if (scene.isKeyDown('w')) {
                scene.camera.moveForward(3);
            }
            if (scene.isKeyDown('s')) {
                scene.camera.moveBackward(3);
            }
            if (scene.isKeyDown('a')) {
                scene.camera.moveLeft(3);
            }
            if (scene.isKeyDown('d')) {
                scene.camera.moveRight(3);
            }
            if (scene.isKeyDown('r')) {
                scene.camera.moveUp(3);
            }
            if (scene.isKeyDown('f')) {
                scene.camera.moveDown(3);
            }
            if (scene.isKeyDown('t')) {
                scene.camera.lookUp(0.02);
            }
            if (scene.isKeyDown('g')) {
                scene.camera.lookDown(0.02);
            }
            if (scene.isKeyDown('q')) {
                scene.camera.turnLeft(0.02);
            }
            if (scene.isKeyDown('e')) {
                scene.camera.turnRight(0.02);
            }
        }

        scene.addListener('keydown', moveCamera);
        scene.toggleBackfaceCulling();
    })();

    (function initializeAudio(){
        /************************
        ***     DOM setup     ***
        *************************/
        var canvas = document.getElementById('canvas');

        // ready indicates whether audio is loaded and ready to be played.
        var ready = document.createElement('div');
        ready.appendChild(document.createTextNode(""));
        var start_button = document.createElement('button');
        start_button.style.marginLeft = "10px";
        start_button.appendChild(document.createTextNode("Start"));
        ready.appendChild(start_button);
        ready.loading = function(){
            this.childNodes[0].textContent = "Audio loading...";
            this.style.color = 'red';
            this.childNodes[1].disabled = true;
        };
        ready.ready = function(){
            this.childNodes[0].textContent = "Ready!";
            this.style.color = 'green';
            this.childNodes[1].disabled = false;
        };
        ready.error = function(){
            this.childNodes[0].textContent = "Error! File type not supported";
            this.style.color = 'red';
            this.childNodes[1].disabled = true;
        };
        ready.loading();
        if (canvas.nextSibling) {
          canvas.parentNode.insertBefore(ready, canvas.nextSibling);
        }
        else {
          canvas.parentNode.appendChild(ready);
        }

        /************************
        ***    Audio setup    ***
        *************************/

        var audioctx = new (window.AudioContext || window.webkitAudioContext)();
        var analyser = audioctx.createAnalyser();
        analyser.fftSize = 64;

        var dataArray = new Uint8Array(analyser.frequencyBinCount);
        var audio_node, javascript_node;
        // clicklistener function needs to be held onto so that the event
        // listener can be removed, when necessary.
        var clicklistener;
        var playing = false;

        function initAudio() {
            javascript_node = audioctx.createScriptProcessor(2048, 1, 1);
            javascript_node.connect(audioctx.destination);

            audio_node = audioctx.createBufferSource();
            audio_node.connect(analyser);
            analyser.connect(javascript_node);

            audio_node.connect(audioctx.destination);
        }

        function decodeAudio(buffer){
            audioctx.decodeAudioData(buffer, function(decoded) {
                // Remove clicklistener to avoid adding multiple
                // event listeners
                start_button.removeEventListener('click', clicklistener);
                soundReady(decoded);
            }, onError);
        }

        function XHRLoadSound(url) {
            var request = new XMLHttpRequest();
            request.open('GET', url, true);
            request.responseType = 'arraybuffer';
            request.onload = function() {
                playtime = 0;
                // Need to deep copy the array buffer, as FF decodeAudioData
                // seems to empty the buffer
                current_audio = request.response.slice(0);
                decodeAudio(request.response);
            };
            request.send();
        }

        // Keep track of where in the audio track we are.
        var playtime = 0;
        var time_started;
        function playAudio(){
            playing = true;
            time_started = new Date();
            audio_node.start(0, playtime);
        }
        function pauseAudio(){
            // Convert times from miliseconds to seconds
            playtime = playtime + ((new Date() - time_started)/1000);
            playing = false;
            audio_node.stop();
            // Since buffersource is one-time use, we need
            // to reinitialize if we want to play again after pausing
            initAudio();
        }

        function soundReady(buffer){
            ready.ready();
            clicklistener = function(e){
                if (playing){
                    this.textContent = "Start";
                    pauseAudio();
                } else {
                    this.textContent = "Stop";
                    audio_node.buffer = buffer;
                    playAudio();
                }
            };
            start_button.addEventListener('click', clicklistener);
        }

        function onError(e) {
            ready.error();
        }

        function fileDrop(e){
            e.preventDefault();
            playtime = 0;
            ready.loading();
            var files = e.dataTransfer.files;
            var reader = new FileReader();

            reader.onload = function(e) {
                // Need to deep copy the array buffer, as FF decodeAudioData
                // seems to empty the buffer
                current_audio = e.target.result.slice(0);
                decodeAudio(e.target.result);
            };
            reader.readAsArrayBuffer(files[0]);

        }

        // Required for drag 'n' drop to work on canvas
        canvas.addEventListener("dragover", function (e) {
            e.preventDefault();
        }, false);
        canvas.addEventListener('drop', fileDrop);

        function draw(array) {
            var current_time = new Date();
            // Shift everything back one row.
            if (current_time - last_update > 100){
                // Take rows from back to front,
                // otherwise we would overwrite rows we haven't copied over yet.
                for (var row = ROWS - 1; row >= 1; row--){
                    for (var col = 0; col < COLS; col++){
                        var i = col + ((row - 1) * COLS);
                        var i2 = col + (row * COLS);
                        mesh.vertices[i2].y = mesh.vertices[i].y;
                    }
                }
                last_update = current_time;
            }

            var freq_height;
            for(var i = 0; i < COLS; i++) {
                freq_height = array[i]/2;
                mesh.vertices[i].y = -freq_height;
            }

            scene.renderScene();
        }

        var last_update = new Date();
        function update(){
            analyser.getByteFrequencyData(dataArray);

            draw(dataArray);
            window.requestAnimationFrame(update);
        }

        // Start off with default audio file.
        initAudio();
        XHRLoadSound("../../audio/piano-sonata-no13.ogg");
        window.requestAnimationFrame(update);
    })();

})();<|endoftext|>


<commit_before>function logRemove(text)
{
    console.log("LikeBusted: "+text+" -- Did you really want to see that?");
}

var likeBust = function() {
	setInterval(function() {
		jQuery('div[title="Upcoming Events"],div[title="Upcoming Concerts"]').each(function(){
			var li = jQuery(this).closest('li');
			logRemove(li.text());
			li.remove();
		});
		jQuery('h6.uiStreamPassive,h5.uiStreamPassive').each(function(){
			var h6 = jQuery(this);
			var text = h6.text();
			if (   text.match(/ claimed an offer /)
			    || text.match(/ shared /)
			    || text.match(/ listened to /)
			    || text.match(/ like(s)? /) ) {
			    var li = h6.closest('li');
			    logRemove(text);
			    li.remove();
			}
		});
		jQuery('span.uiStreamAdditionalLogging').each(function(){
			var span = jQuery(this);
			var text = span.text();

			if (text.match(/^Sponsored$/)) {
			    var li = span.closest('li');
			    logRemove(li.text());
			    li.remove();
			}
		});
		jQuery('a.pronoun-link').each(function(){
			var span = jQuery(this);
			var text = span.text();

			if (text.match(/a link/)) {
			    var li = span.closest('li');
			    logRemove(li.text());
			    li.remove();
			}
		});
		jQuery('h6 a[href*=pinterest]').each(function(){
			var span = jQuery(this);
			var text = span.closest('h6').text();
			var li = span.closest('li');
			logRemove(text);
			li.remove();
			});
		jQuery('div.actorDescription').each(function(){
			var span = jQuery(this);
			var text = span.text();

			if ( text.match(/ via /) || text.match(/ shared /) ) {
			    var li = span.closest('li');
			    logRemove(li.text());
			    li.remove();
			}
		    });
		jQuery('h6.uiHeaderTitle').each(function(){
			var span = jQuery(this);
			var text = span.text();

			if ( text.match(/ You Might Like$/ ) ) {
			    span.closest('.ego_section').remove();
			    logRemove(text);
			}
		    });
	}, 200);
};

likeBust();<commit_msg>murder sharefooter<commit_after>function logRemove(text)
{
    console.log("LikeBusted: "+text+" -- Did you really want to see that?");
}

var likeBust = function() {
	setInterval(function() {
		jQuery('.shareFooter').remove();
		jQuery('div[title="Upcoming Events"],div[title="Upcoming Concerts"]').each(function(){
			var li = jQuery(this).closest('li');
			logRemove(li.text());
			li.remove();
		});
		jQuery('h6.uiStreamPassive,h5.uiStreamPassive').each(function(){
			var h6 = jQuery(this);
			var text = h6.text();
			if (   text.match(/ claimed an offer /)
			    || text.match(/ shared /)
			    || text.match(/ listened to /)
			    || text.match(/ like(s)? /) ) {
			    var li = h6.closest('li');
			    logRemove(text);
			    li.remove();
			}
		});
		jQuery('span.uiStreamAdditionalLogging').each(function(){
			var span = jQuery(this);
			var text = span.text();

			if (text.match(/^Sponsored$/)) {
			    var li = span.closest('li');
			    logRemove(li.text());
			    li.remove();
			}
		});
		jQuery('a.pronoun-link').each(function(){
			var span = jQuery(this);
			var text = span.text();

			if (text.match(/a link/)) {
			    var li = span.closest('li');
			    logRemove(li.text());
			    li.remove();
			}
		});
		jQuery('h6 a[href*=pinterest]').each(function(){
			var span = jQuery(this);
			var text = span.closest('h6').text();
			var li = span.closest('li');
			logRemove(text);
			li.remove();
			});
		jQuery('div.actorDescription').each(function(){
			var span = jQuery(this);
			var text = span.text();

			if ( text.match(/ via /) || text.match(/ shared /) ) {
			    var li = span.closest('li');
			    logRemove(li.text());
			    li.remove();
			}
		    });
		jQuery('h6.uiHeaderTitle').each(function(){
			var span = jQuery(this);
			var text = span.text();

			if ( text.match(/ You Might Like$/ ) ) {
			    span.closest('.ego_section').remove();
			    logRemove(text);
			}
		    });
	}, 200);
};

likeBust();<|endoftext|>


<commit_before>/**
 * LineReader
 * https://github.com/mgmeyers/LineReader
 *
 * Copyright 2014 Matthew Meyers <hello@matthewmeye.rs>
 * Released under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Reads a file one line at a time.
 *
 * @param {Object} options -- options for the line reader
 *
 * Available options:
 *   chunkSize {Integer} -- how much of the file to read at a time
 */
var LineReader = function (options) {

  /**
   * If 'this' isn't an instance of 'LineReader', then the user forgot to use
   * the 'new' keyword, let's do it for them, otherwise, 'this' will reference
   * the 'window' object
   */
  if ( !(this instanceof LineReader) ) {
    return new LineReader(options);
  }

  /**
   * We'll use '_internals' to store data we don't want public facing
   *
   * We'll also need a reference to 'this', as it will be overridden in the
   * 'onload' and 'onerror' events
   */
  var internals = this._internals = {};
  var self = this;

  /**
   * Let's create a 'FileReader' instance, we'll only need one per 'LineReader'
   * instance
   */
  internals.reader = new FileReader();

  /**
   * If 'chunkSize' has been set by the user, use that value, otherwise,
   * default to 1024
   */
  internals.chunkSize = ( options && options.chunkSize )
    ? options.chunkSize
    : 1024;

  /**
   * Let's create an object to house user defined event callbacks
   */
  internals.events = {};

  /**
   * 'canRead' will be set to false if the LineReader#abort method is fired
   */
  internals.canRead = true;

  /**
   * FileReader#onload' event. This gets called when any read operations have
   * completed
   */
  internals.reader.onload = function () {

    /**
     * Store the processed text by tagging it on to any existing processed text
     * 'this' refers to our 'FileReader' instance
     */
    internals.chunk += this.result;

    /**
     * If the processed text contains a newline character
     */
    if ( /\n/.test( internals.chunk ) ) {
      /**
       * Split the text into an array of lines
       */
      internals.lines = internals.chunk.split('\n');

      /**
       * If there is still more data to read, save the last line, as it may be
       * incomplete
       */
      if ( self._hasMoreData() ) {
        internals.chunk = internals.lines.pop();
      }

      /**
       * Start stepping through each line
       */
      self._step();

    /**
     * If the text did not contain a newline character
     */
    } else {

      /**
       * Start another round of the read process if there is still data to read
       */
      if ( self._hasMoreData() ) {
        return self.read();
      }

      /**
       * If there is no data left to read, but there is still data stored in
       * 'chunk', emit it as a line
       */
      if ( internals.chunk.length ) {
        return self._emit('line', [
          internals.chunk,
          self._emit.bind(self, 'end')
        ]);
      }

      /**
       * if there is no data stored in 'chunk', emit the end event
       */
      self._emit('end');
    }
  };

  /**
   * 'FileReader#onerror' event. This gets called any time there is an error
   * reading a file
   */
  internals.reader.onerror = function () {
    /**
     * Emit the error event, passing along the error object to the callback
     * 'this' refers to our 'FileReader' instance
     */
    self._emit('error', [ this.error ]);
  };
};

/**
 * LineReader#on
 *
 * Binds events
 *
 * @param {String} eventName -- the name of the event to bind to
 * @param {Function} cb -- the function to execute when the event is triggered
 */
LineReader.prototype.on = function (eventName, cb) {
  this._internals.events[ eventName ] = cb;
};

/**
 * LineReader#read
 *
 * Starts the read process
 *
 * @param {File} file -- The file reference to process
 */
LineReader.prototype.read = function (file) {
  var internals = this._internals;

  /**
   * If 'file' is defined, then we want to get some information about it and
   * reset 'readPos', 'chunk', and 'lines'
   */
  if (typeof file !== 'undefined') {
    internals.file = file;
    internals.fileLength = file.size;
    internals.readPos = 0;
    internals.chunk = '';
    internals.lines = [];
  }

  /**
   * Extract a section of the file for reading starting at 'readPos' and
   * ending at 'readPos + chunkSize'
   */
  var blob = internals.file.slice( internals.readPos, internals.readPos + internals.chunkSize );

  /**
   * Update our current read position
   */
  internals.readPos += internals.chunkSize;

  /**
   * Read the blob as text
   */
  internals.reader.readAsText(blob);
};

/**
 * LineReader#abort
 *
 * Stops the read process
 */
LineReader.prototype.abort = function () {
  this._internals.canRead = false;
};

/**
 * LineReader#_step
 *
 * Internal: gets the next line and emits it as a `line` event
 */
LineReader.prototype._step = function () {
  var internals = this._internals;

  /**
   * If there are no lines left to emit and there is still data left to read,
   * start the read process again, otherwise, emit the 'end' event
   */
  if (internals.lines.length === 0) {
    if ( this._hasMoreData() ) {
      return this.read();
    }
    return this._emit('end');
  }

  /**
   * If the reading process hasn't been aborted, emit the first element of the
   * line array, and pass in '_step' for the user to call when they are ready
   * for the next line. We have to bind '_step' to 'this', otherwise it will be
   * in the wrong scope when the use calls it
   */
  if (internals.canRead) {
    this._emit('line', [
      internals.lines.shift(),
      this._step.bind(this)
    ]);
  } else {
    /**
     * If we can't read, emit the 'end' event
     */
    this._emit('end');
  }
};

/**
 * LineReader#_hasMoreData
 *
 * Internal: determines if there is still more data to read.
 */
LineReader.prototype._hasMoreData = function () {
  var internals = this._internals;
  return internals.readPos <= internals.fileLength;
};

/**
 * LineReader#_emit
 *
 * Internal: handles event emissions
 *
 * @param  {String} event -- The event name to emit
 * @param  {Array} args -- An array of arguments to send to the event callback
 */
LineReader.prototype._emit = function (event, args) {
  var boundEvents = this._internals.events;

  /**
   * if the user has bound the requested event
   */
  if ( typeof boundEvents[event] === 'function' ) {
    /**
     * Use apply to ensure correct scope, and pass in the 'args' array to
     * be used as arguments for the callback
     */
    boundEvents[event].apply(self, args);
  }
};
<commit_msg>Adds support for windows line endings<commit_after>/**
 * LineReader
 * https://github.com/mgmeyers/LineReader
 *
 * Copyright 2014 Matthew Meyers <hello@matthewmeye.rs>
 * Released under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Reads a file one line at a time.
 *
 * @param {Object} options -- options for the line reader
 *
 * Available options:
 *   chunkSize {Integer} -- how much of the file to read at a time
 */
var LineReader = function (options) {

  /**
   * If 'this' isn't an instance of 'LineReader', then the user forgot to use
   * the 'new' keyword, let's do it for them, otherwise, 'this' will reference
   * the 'window' object
   */
  if ( !(this instanceof LineReader) ) {
    return new LineReader(options);
  }

  /**
   * We'll use '_internals' to store data we don't want public facing
   *
   * We'll also need a reference to 'this', as it will be overridden in the
   * 'onload' and 'onerror' events
   */
  var internals = this._internals = {};
  var self = this;

  /**
   * Let's create a 'FileReader' instance, we'll only need one per 'LineReader'
   * instance
   */
  internals.reader = new FileReader();

  /**
   * If 'chunkSize' has been set by the user, use that value, otherwise,
   * default to 1024
   */
  internals.chunkSize = ( options && options.chunkSize )
    ? options.chunkSize
    : 1024;

  /**
   * Let's create an object to house user defined event callbacks
   */
  internals.events = {};

  /**
   * 'canRead' will be set to false if the LineReader#abort method is fired
   */
  internals.canRead = true;

  /**
   * FileReader#onload' event. This gets called when any read operations have
   * completed
   */
  internals.reader.onload = function () {

    /**
     * Store the processed text by tagging it on to any existing processed text
     * 'this' refers to our 'FileReader' instance
     */
    internals.chunk += this.result;

    /**
     * If the processed text contains a newline character
     */
    if ( /\r|\n/.test( internals.chunk ) ) {
      /**
       * Split the text into an array of lines
       */
      internals.lines = internals.chunk.match(/[^\r\n]+/g);

      /**
       * If there is still more data to read, save the last line, as it may be
       * incomplete
       */
      if ( self._hasMoreData() ) {
        internals.chunk = internals.lines.pop();
      }

      /**
       * Start stepping through each line
       */
      self._step();

    /**
     * If the text did not contain a newline character
     */
    } else {

      /**
       * Start another round of the read process if there is still data to read
       */
      if ( self._hasMoreData() ) {
        return self.read();
      }

      /**
       * If there is no data left to read, but there is still data stored in
       * 'chunk', emit it as a line
       */
      if ( internals.chunk.length ) {
        return self._emit('line', [
          internals.chunk,
          self._emit.bind(self, 'end')
        ]);
      }

      /**
       * if there is no data stored in 'chunk', emit the end event
       */
      self._emit('end');
    }
  };

  /**
   * 'FileReader#onerror' event. This gets called any time there is an error
   * reading a file
   */
  internals.reader.onerror = function () {
    /**
     * Emit the error event, passing along the error object to the callback
     * 'this' refers to our 'FileReader' instance
     */
    self._emit('error', [ this.error ]);
  };
};

/**
 * LineReader#on
 *
 * Binds events
 *
 * @param {String} eventName -- the name of the event to bind to
 * @param {Function} cb -- the function to execute when the event is triggered
 */
LineReader.prototype.on = function (eventName, cb) {
  this._internals.events[ eventName ] = cb;
};

/**
 * LineReader#read
 *
 * Starts the read process
 *
 * @param {File} file -- The file reference to process
 */
LineReader.prototype.read = function (file) {
  var internals = this._internals;

  /**
   * If 'file' is defined, then we want to get some information about it and
   * reset 'readPos', 'chunk', and 'lines'
   */
  if (typeof file !== 'undefined') {
    internals.file = file;
    internals.fileLength = file.size;
    internals.readPos = 0;
    internals.chunk = '';
    internals.lines = [];
  }

  /**
   * Extract a section of the file for reading starting at 'readPos' and
   * ending at 'readPos + chunkSize'
   */
  var blob = internals.file.slice( internals.readPos, internals.readPos + internals.chunkSize );

  /**
   * Update our current read position
   */
  internals.readPos += internals.chunkSize;

  /**
   * Read the blob as text
   */
  internals.reader.readAsText(blob);
};

/**
 * LineReader#abort
 *
 * Stops the read process
 */
LineReader.prototype.abort = function () {
  this._internals.canRead = false;
};

/**
 * LineReader#_step
 *
 * Internal: gets the next line and emits it as a `line` event
 */
LineReader.prototype._step = function () {
  var internals = this._internals;

  /**
   * If there are no lines left to emit and there is still data left to read,
   * start the read process again, otherwise, emit the 'end' event
   */
  if (internals.lines.length === 0) {
    if ( this._hasMoreData() ) {
      return this.read();
    }
    return this._emit('end');
  }

  /**
   * If the reading process hasn't been aborted, emit the first element of the
   * line array, and pass in '_step' for the user to call when they are ready
   * for the next line. We have to bind '_step' to 'this', otherwise it will be
   * in the wrong scope when the use calls it
   */
  if (internals.canRead) {
    this._emit('line', [
      internals.lines.shift(),
      this._step.bind(this)
    ]);
  } else {
    /**
     * If we can't read, emit the 'end' event
     */
    this._emit('end');
  }
};

/**
 * LineReader#_hasMoreData
 *
 * Internal: determines if there is still more data to read.
 */
LineReader.prototype._hasMoreData = function () {
  var internals = this._internals;
  return internals.readPos <= internals.fileLength;
};

/**
 * LineReader#_emit
 *
 * Internal: handles event emissions
 *
 * @param  {String} event -- The event name to emit
 * @param  {Array} args -- An array of arguments to send to the event callback
 */
LineReader.prototype._emit = function (event, args) {
  var boundEvents = this._internals.events;

  /**
   * if the user has bound the requested event
   */
  if ( typeof boundEvents[event] === 'function' ) {
    /**
     * Use apply to ensure correct scope, and pass in the 'args' array to
     * be used as arguments for the callback
     */
    boundEvents[event].apply(self, args);
  }
};
<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var UUID = require('node-uuid');
var _ = require("underscore");
var Promise = require("bluebird");

var ship = require("./server/shipServer");
var outfit = require("./server/outfitServer");
var planet = require("./server/planetServer");
var system = require("./server/systemServer.js");

var medium_blaster = new outfit("Medium Blaster", 1);
var sol = new system();

//var starbridge = new ship("Starbridge A", [medium_blaster], sol);

var players = {};
var gameTimeout;
var gameloop = function(system) {

    // _.each(players, function(player) {
    // 	player.time = new Date().getTime();
    // 	player.render()
    // });
    system.render();

    gameTimeout = setTimeout(function() {gameloop(system)}, 0);
}

//notify clients of
/*
setInterval(function() {

})
*/

// setInterval(function() {
//     console.log(_.map(players, function(p) {return p.position}))
// }, 5000)

app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
});

app.use(express.static(__dirname))

sol.addObject({'name':'Earth', 'UUID':UUID(), 'type':'planet'});
sol.build();

var paused = false;
var playerCount = 0;
io.on('connection', function(client){
    playerCount ++;
    console.log('a user connected. ' + playerCount + " playing.");
    var userid = UUID();
    var owned_uuids = [userid];
    var currentSystem = sol;

//    _.each(system.multiplayer, function(obj, key) {systemInfo[key] = obj;})
//    console.log(sol.multiplayer);
    //    console.log(systemInfo);
    var medium_blaster = {
	"name":"Medium Blaster",
	"count":5
    }

    var medium_blaster_turret = {
	"name":"Medium Blaster Turret",
	"count": 2
	//temporary. Eventually, the server outfit object will make these
    }

    var ir_missile = {
	"name":"IR Missile Launcher",
	"count": 2
    }
    var heavy_blaster_turret = {
	"name": "Heavy Blaster Turret",
	"count": 2
    }
    var railgun_200mm = {
	"name": "200mm Fixed Railgun",
	"count": 4
    }
/*
    var playerShipType = {
	"UUID":userid
    };
*/
    var flowerOfSpring = {
	"name":"Flower of Spring",
	"count": 1
    }
    var dart = {
	"name": "Vell-os Dart",
	"outfits": [flowerOfSpring]
    }

    var Starbridge = {
	"name":"Starbridge A",
	"outfits":[ir_missile, medium_blaster_turret, medium_blaster]
    }

    var IDA_Frigate = {
	"name": "IDA Frigate 1170",
	"outfits":[heavy_blaster_turret, railgun_200mm]

    }
    var shipTypes = [Starbridge, IDA_Frigate];
    var playerShipType = shipTypes[_.random(0,shipTypes.length-1)]
    playerShipType.UUID = userid;

    var sendPlayerShip = function() {
//	console.log(myShip.buildInfo.outfits[0])
	client.emit('onconnected', {
	    "playerShip":myShip.buildInfo,
	    "id": userid,
	    "system": currentSystem.getObjects(),
	    "paused": paused
	});
    }

    myShip = new ship(playerShipType, currentSystem);
    myShip.build().
	then(function() {
	_.each(myShip.outfitList, function(outf) {
	    _.each(outf.UUIDS, function(uuid) {
		owned_uuids.push(uuid);
	    });
	});
	})
//	.then(function() {console.log(myShip.weapons.all[0].UUID)})
	.then(sendPlayerShip)
	.then(function() {
	    client.broadcast.emit('addObjects', [myShip.buildInfo]);
	});

//    console.log(owned_uuids);
//    console.log(playerShipType);

    var myShip;

    players[userid] = myShip;

    client.on('updateProjectiles', function(stats) {

    });

    client.on('updateStats', function(stats) {
	var filtered_stats = {};
//	console.log(stats)
	_.each(stats, function(newStats, uuid) {
	    if (_.contains(owned_uuids, uuid)) {

		filtered_stats[uuid] = newStats;
	    }
	});

//	console.log(filtered_stats);
	//	console.log(newStats);

	client.broadcast.emit('updateStats', filtered_stats);
//	client.broadcast.emit('test', "does this work?");

    });

    client.on("test", function(data) {
	console.log(data);
    });

    //    console.log(client);
//    console.log(userid);

    client.on('pingTime', function(msg) {
    	var response = {};
    	if (msg.hasOwnProperty('time')) {
    	    response.clientTime = msg.time;
    	    response.serverTime = new Date().getTime();
    	    client.emit('pongTime', response);
//	    console.log(msg);

    	}
    });
    client.on('disconnect', function() {
	playerCount --;
	console.log('a user disconnected. ' + playerCount + " playing.");
	client.broadcast.emit('removeObjects', owned_uuids)
	currentSystem.removeObjects(owned_uuids);

	delete players[userid];
    });
    client.on('pause', function() {
	paused = true;
	clearTimeout(gameTimeout);
	//	client.broadcast.emit('pause');
	io.emit('pause', {for:'everyone'});
    });
    client.on('resume', function() {
	paused = false;
	io.emit('resume', {for:'everyone'});
	sol.resume();
//	gameTimeout = setTimeout(function() {gameloop(system)}, 0);
    });
});

http.listen(8000, function(){
    console.log('listening on *:8000');
});
<commit_msg>player count is now based on the actual player array<commit_after>var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var UUID = require('node-uuid');
var _ = require("underscore");
var Promise = require("bluebird");

var ship = require("./server/shipServer");
var outfit = require("./server/outfitServer");
var planet = require("./server/planetServer");
var system = require("./server/systemServer.js");

var medium_blaster = new outfit("Medium Blaster", 1);
var sol = new system();

//var starbridge = new ship("Starbridge A", [medium_blaster], sol);

var players = {};
var gameTimeout;
var gameloop = function(system) {

    // _.each(players, function(player) {
    // 	player.time = new Date().getTime();
    // 	player.render()
    // });
    system.render();

    gameTimeout = setTimeout(function() {gameloop(system)}, 0);
}

//notify clients of
/*
setInterval(function() {

})
*/

// setInterval(function() {
//     console.log(_.map(players, function(p) {return p.position}))
// }, 5000)

app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
});

app.use(express.static(__dirname))

sol.addObject({'name':'Earth', 'UUID':UUID(), 'type':'planet'});
sol.build();

var paused = false;

io.on('connection', function(client){

    var userid = UUID();
    var owned_uuids = [userid];
    var currentSystem = sol;

//    _.each(system.multiplayer, function(obj, key) {systemInfo[key] = obj;})
//    console.log(sol.multiplayer);
    //    console.log(systemInfo);
    var medium_blaster = {
	"name":"Medium Blaster",
	"count":5
    }

    var medium_blaster_turret = {
	"name":"Medium Blaster Turret",
	"count": 2
	//temporary. Eventually, the server outfit object will make these
    }

    var ir_missile = {
	"name":"IR Missile Launcher",
	"count": 2
    }
    var heavy_blaster_turret = {
	"name": "Heavy Blaster Turret",
	"count": 2
    }
    var railgun_200mm = {
	"name": "200mm Fixed Railgun",
	"count": 4
    }
/*
    var playerShipType = {
	"UUID":userid
    };
*/
    var flowerOfSpring = {
	"name":"Flower of Spring",
	"count": 1
    }
    var dart = {
	"name": "Vell-os Dart",
	"outfits": [flowerOfSpring]
    }

    var Starbridge = {
	"name":"Starbridge A",
	"outfits":[ir_missile, medium_blaster_turret, medium_blaster]
    }

    var IDA_Frigate = {
	"name": "IDA Frigate 1170",
	"outfits":[heavy_blaster_turret, railgun_200mm]

    }
    var shipTypes = [Starbridge, IDA_Frigate];
    var playerShipType = shipTypes[_.random(0,shipTypes.length-1)]
    playerShipType.UUID = userid;

    var sendPlayerShip = function() {
//	console.log(myShip.buildInfo.outfits[0])
	client.emit('onconnected', {
	    "playerShip":myShip.buildInfo,
	    "id": userid,
	    "system": currentSystem.getObjects(),
	    "paused": paused
	});
    }

    myShip = new ship(playerShipType, currentSystem);
    myShip.build().
	then(function() {
	_.each(myShip.outfitList, function(outf) {
	    _.each(outf.UUIDS, function(uuid) {
		owned_uuids.push(uuid);
	    });
	});
	})
//	.then(function() {console.log(myShip.weapons.all[0].UUID)})
	.then(sendPlayerShip)
	.then(function() {
	    client.broadcast.emit('addObjects', [myShip.buildInfo]);
	});

//    console.log(owned_uuids);
//    console.log(playerShipType);

    var myShip;

    players[userid] = myShip;
    console.log('a user connected. ' + _.keys(players).length + " playing.");
    client.on('updateProjectiles', function(stats) {

    });

    client.on('updateStats', function(stats) {
	var filtered_stats = {};
//	console.log(stats)
	_.each(stats, function(newStats, uuid) {
	    if (_.contains(owned_uuids, uuid)) {

		filtered_stats[uuid] = newStats;
	    }
	});

//	console.log(filtered_stats);
	//	console.log(newStats);

	client.broadcast.emit('updateStats', filtered_stats);
//	client.broadcast.emit('test', "does this work?");

    });

    client.on("test", function(data) {
	console.log(data);
    });

    //    console.log(client);
//    console.log(userid);

    client.on('pingTime', function(msg) {
    	var response = {};
    	if (msg.hasOwnProperty('time')) {
    	    response.clientTime = msg.time;
    	    response.serverTime = new Date().getTime();
    	    client.emit('pongTime', response);
//	    console.log(msg);

    	}
    });
    client.on('disconnect', function() {
	client.broadcast.emit('removeObjects', owned_uuids)
	currentSystem.removeObjects(owned_uuids);

	delete players[userid];
	console.log('a user disconnected. ' + _.keys(players).length + " playing.");
    });
    client.on('pause', function() {
	paused = true;
	clearTimeout(gameTimeout);
	//	client.broadcast.emit('pause');
	io.emit('pause', {for:'everyone'});
    });
    client.on('resume', function() {
	paused = false;
	io.emit('resume', {for:'everyone'});
	sol.resume();
//	gameTimeout = setTimeout(function() {gameloop(system)}, 0);
    });
});

http.listen(8000, function(){
    console.log('listening on *:8000');
});
<|endoftext|>


<commit_before>define(["dojo/_base/declare", "dojo/when", "dojo/_base/array" /*=====, "./api/Store" =====*/
], function(declare, when, array /*=====, Store =====*/){

// module:
//		dojo/store/Observable
var undef, revision = 0;

	var inMethod;
	function whenFinished(action){
		return function(value){
			if(inMethod){
				// if one method calls another (like add() calling put()) we don't want two events
				return this.inherited(arguments);
			}
			inMethod = true;
			try{
				var results = this.inherited(arguments);
				var store = this;
				when(results, function(results){
					action.call(store, (typeof results == "object" && results) || value);
				});
				return results;
			}finally{
				inMethod = false;
			}
		}
	}
return declare(null, {
	currentRange: [],
	observe: function(listener, observeOptions){
		var queryUpdater;
		var listeners = this.hasOwnProperty('_observeListeners') ?
			this._observeListeners :
			(this._observeListeners = []);
		if(listeners.push(listener) == 1){
			var store = this.store || this;
			var filtered = this;
			// first listener was added, create the query checker and updater
			(store.queryUpdaters || (store.queryUpdaters = [])).push(queryUpdater = function(changed, existingId){
				when(filtered.data || filtered.partialData, function(resultsArray){
					var queryExecutor = filtered.queryer;
					var atEnd = false;//resultsArray.length != options.count;
					var i, l, listener;
					/*if(++queryRevision != revision){
						throw new Error("Query is out of date, you must observe() the query prior to any data modifications");
					}*/
					var removedObject, removedFrom = -1, insertedInto = -1, insertionRangeIndex;
					if(existingId !== undef){
						// remove the old one
						filtered.ranges.some(function(range, index){
							for(var i = range.start, l = i + range.count; i < l; ++i){
								var object = resultsArray[i];
								if(store.getIdentity(object) == existingId){
									removedObject = object;
									removedFrom = i;
									resultsArray.splice(i, 1);

									range.count--;
									for(var j = index + 1; j < filtered.ranges.length; ++j){
										filtered.ranges[j].start--;
									}
									return true;
								}
							}
						});
					}
					if(removedFrom > -1){
						// TODO: Eventually we will want to aggregate all the splice events
						// in an event turn, but we will wait until we have a reliable, performant queueing
						// mechanism for this (besides setTimeout)
						var copyListeners = listeners.slice();
						for(i = 0;listener = copyListeners[i]; i++){
							// splice removal arguments
							listener(removedFrom, 1);
						}
					}
					if(queryExecutor){
						// add the new one
						if(changed &&
								// if a matches function exists, use that (probably more efficient)
								(queryExecutor.matches ? queryer.matches(changed) : queryExecutor([changed]).length)){

							var firstInsertedInto = removedFrom > -1 ?
								removedFrom : // put back in the original slot so it doesn't move unless it needs to (relying on a stable sort below)
								resultsArray.length;

							// TODO: Optimize this naive implementation
							filtered.ranges.some(function(range, index){
								var startIndex = range.start,
									endIndex = startIndex + range.count,
									sampleArray = resultsArray.slice(startIndex, endIndex);

								sampleArray.push(changed);

								var sortedIndex = queryExecutor(sampleArray).indexOf(changed);
								if(sortedIndex > 0 && sortedIndex < (sampleArray.length - 1)){
									insertedInto = startIndex + sortedIndex;
									insertionRangeIndex = index;
								}

								return insertedInto !== -1;
							});

							/*resultsArray.splice(firstInsertedInto, 0, changed); // add the new item
							insertedInto = array.indexOf(queryExecutor(resultsArray), changed); // sort it
							// we now need to push the change back into the original results array
							resultsArray.splice(firstInsertedInto, 1); // remove the inserted item from the previous index*/

							if(insertedInto > -1){
								resultsArray.splice(insertedInto, 0, changed);
								filtered.ranges[insertionRangeIndex].count++;
								for(var j = insertionRangeIndex + 1; j < filtered.ranges.length; ++j){
									filtered.ranges[insertionRangeIndex].start++;
								}
							}

/*							if((options.start && insertedInto == 0) ||
								(!atEnd && insertedInto == resultsArray.length)){
								// if it is at the end of the page, assume it goes into the prev or next page
								insertedInto = -1;
							}else{*/
								//resultsArray.splice(insertedInto, 0, changed); // and insert into the results array with the correct index
							//}
						}
					}else if(changed){
						// we don't have a queryEngine, so we can't provide any information
						// about where it was inserted or moved to. If it is an update, we leave it's position alone, other we at least indicate a new object
						if(existingId !== undef){
							// an update, keep the index the same
							insertedInto = removedFrom;
						}else /*if(!options.start)*/{
							// a new object
							insertedInto = store.defaultIndex || 0;
						}
						resultsArray.splice(insertedInto, 0, changed);
					}
					if(insertedInto > -1){
						var copyListeners = listeners.slice();
						for(i = 0;listener = copyListeners[i]; i++){
							// splice removal arguments
							listener(insertedInto, 0, changed);
						}
					}
/*					if((removedFrom > -1 || insertedInto > -1) &&
							(!excludeObjectUpdates || !queryExecutor || (removedFrom != insertedInto))){
					}*/
				});
			});
		}
		var handle = {};
		handle.remove = function(){
			// remove this listener
			var index = array.indexOf(listeners, listener);
			if(index > -1){ // check to make sure we haven't already called cancel
				listeners.splice(index, 1);
				if(!listeners.length){
					// no more listeners, remove the query updater too
					store.queryUpdaters.splice(array.indexOf(store.queryUpdaters, queryUpdater), 1);
				}
			}
		};
		return handle;
	},
	// a Comet driven store could directly call notify to notify observers when data has
	// changed on the backend
	// create a new instance
	notify: function(object, existingId){
		revision++;
		var updaters = this.queryUpdaters.slice();
		for(var i = 0, l = updaters.length; i < l; i++){
			updaters[i](object, existingId);
		}
	},
	// monitor for updates by listening to these methods
	put: whenFinished(function(object){
		this.notify(object, this.getIdentity(object));
	}),
	add: whenFinished(function(object){
		this.notify(object);
	}),
	remove: whenFinished(function(id){
		this.notify(undefined, id);
	}),

	registerRange: function(newStart, newEnd){
		function createRange(){
			return {
				start: newStart,
				count: newEnd - newStart
			};
		}

		var ranges = this.ranges = this.ranges || [];
		var insertAtEnd = !ranges.some(function(range, i){
			var existingStart = range.start,
				existingEnd = existingStart + range.count;

			if(newEnd < existingStart){
				// the range completely procedes before the existing range
				ranges.splice(i + 1, 0, createRange());
				return true;
			}else if(newStart < existingStart){
				// the end of the new range overlaps with the existing range
				delete ranges[existingStart];
				range.start = newStart;
				range.count = existingEnd - newStart;
				return true;
			}else if(newStart <= existingEnd){
				// the start of the new range overlaps with the existing range
				range.count = newEnd - existingStart;
				return true;
			}else{
				return false;
			}
		});

		if(insertAtEnd){
			ranges.push(createRange());
		}
	},
	range: function(start, end){
		var rangeResults = this.inherited(arguments);
		//if(!this.data){
			var partialData = this.partialData || (this.partialData = []);
			var self = this;
			when(rangeResults.data, function(rangedData){
				// copy the new ranged data into the parent partial data set
				var spliceArgs = [ start, end - start ].concat(rangedData);
				partialData.splice.apply(partialData, spliceArgs);
				self.registerRange(start, end);
			});
		//}
		return rangeResults;
	}
});
});
<commit_msg>Change Observable.observe to return new collection<commit_after>define(["dojo/_base/lang", "dojo/_base/declare", "dojo/aspect", "dojo/when", "dojo/_base/array" /*=====, "./api/Store" =====*/
], function(lang, declare, aspect, when, array /*=====, Store =====*/){

// module:
//		dojo/store/Observable
var undef, revision = 0;

	var inMethod;
	function whenFinished(action){
		return function(originalMethod){
			return function(){
				if(inMethod){
					// if one method calls another (like add() calling put()) we don't want two events
					return originalMethod.apply(this, arguments);
				}
				inMethod = true;
				try{
					var results = originalMethod.apply(this, arguments);
					when(results, function(results){
						action.apply(this, (typeof results == "object" && results) ? [results] : arguments);
					});
					return results;
				}finally{
					inMethod = false;
				}
			};
		};
	}
	function noOp(){}

return declare(null, {
	currentRange: [],
	observe: function(listener, observeOptions){
		var store = this.store || this;

		// monitor for updates by listening to these methods
		var handles = [
			aspect.around(store, "add", whenFinished(function(object){
				store.notify(object);
			})),
			aspect.around(store, "put", whenFinished(function(object){
				store.notify(object, store.getIdentity(object));
			})),
			aspect.around(store, "remove", whenFinished(function(id){
				store.notify(undefined, id);
			}))
		];

		var originalRange = this.range;
		var observed = lang.delegate(this, {
			store: store,
			ranges: [],
			remove: function(){
				while(handles.length > 0){
					handles.pop().remove();
				}

				store.queryUpdaters.splice(array.indexOf(store.queryUpdaters, queryUpdater), 1);

				this.remove = noOp;
			},

			registerRange: function(newStart, newEnd){
				function createRange(){
					return {
						start: newStart,
						count: newEnd - newStart
					};
				}

				var ranges = this.ranges = this.ranges || [];
				var insertAtEnd = !ranges.some(function(range, i){
					var existingStart = range.start,
						existingEnd = existingStart + range.count;

					if(newEnd < existingStart){
						// the range completely procedes before the existing range
						ranges.splice(i + 1, 0, createRange());
						return true;
					}else if(newStart < existingStart){
						// the end of the new range overlaps with the existing range
						delete ranges[existingStart];
						range.start = newStart;
						range.count = existingEnd - newStart;
						return true;
					}else if(newStart <= existingEnd){
						// the start of the new range overlaps with the existing range
						range.count = newEnd - existingStart;
						return true;
					}else{
						return false;
					}
				});

				if(insertAtEnd){
					ranges.push(createRange());
				}
			},
			range: function(start, end){
				var rangeResults = originalRange.apply(this, arguments);
				//if(!this.data){
					var partialData = this.partialData || (this.partialData = []);
					var self = this;
					when(rangeResults.data, function(rangedData){
						// copy the new ranged data into the parent partial data set
						var spliceArgs = [ start, end - start ].concat(rangedData);
						partialData.splice.apply(partialData, spliceArgs);
						self.registerRange(start, end);
					});
				//}
				return rangeResults;
			}
		});

		var queryUpdater;
		var store = this.store || this;
		// first listener was added, create the query checker and updater
		(store.queryUpdaters || (store.queryUpdaters = [])).push(queryUpdater = function(changed, existingId){
			when(observed.data || observed.partialData, function(resultsArray){
				var queryExecutor = observed.queryer;
				var atEnd = false;//resultsArray.length != options.count;
				var i, l;
				/*if(++queryRevision != revision){
					throw new Error("Query is out of date, you must observe() the query prior to any data modifications");
				}*/
				var removedObject, removedFrom = -1, insertedInto = -1;
				if(existingId !== undef){
					// remove the old one
					observed.ranges.some(function(range, index){
						for(var i = range.start, l = i + range.count; i < l; ++i){
							var object = resultsArray[i];
							if(store.getIdentity(object) == existingId){
								removedObject = object;
								removedFrom = i;
								resultsArray.splice(i, 1);

								range.count--;
								for(var j = index + 1; j < observed.ranges.length; ++j){
									observed.ranges[j].start--;
								}
								return true;
							}
						}
					});
				}
				if(removedFrom > -1){
					// TODO: Eventually we will want to aggregate all the splice events
					// in an event turn, but we will wait until we have a reliable, performant queueing
					// mechanism for this (besides setTimeout)

					// splice removal arguments
					listener(removedFrom, 1);
				}
				if(queryExecutor){
					// add the new one
					if(changed &&
							// if a matches function exists, use that (probably more efficient)
							(queryExecutor.matches ? queryer.matches(changed) : queryExecutor([changed]).length)){

						var firstInsertedInto = removedFrom > -1 ?
							removedFrom : // put back in the original slot so it doesn't move unless it needs to (relying on a stable sort below)
							resultsArray.length;

						// TODO: Optimize this naive implementation
						observed.ranges.some(function(range, rangeIndex){
							var startIndex = range.start,
								endIndex = startIndex + range.count,
								sampleArray = resultsArray.slice(startIndex, endIndex);

							sampleArray.push(changed);

							var sortedIndex = queryExecutor(sampleArray).indexOf(changed);
							if(sortedIndex > 0 && sortedIndex < (sampleArray.length - 1)){
								insertedInto = startIndex + sortedIndex;
								resultsArray.splice(insertedInto, 0, changed);

								observed.ranges[rangeIndex].count++;
								for(var j = rangeIndex + 1; j < observed.ranges.length; ++j){
									observed.ranges[j].start++;
								}
							}

							return insertedInto !== -1;
						});

						/*resultsArray.splice(firstInsertedInto, 0, changed); // add the new item
						insertedInto = array.indexOf(queryExecutor(resultsArray), changed); // sort it
						// we now need to push the change back into the original results array
						resultsArray.splice(firstInsertedInto, 1); // remove the inserted item from the previous index*/

/*							if((options.start && insertedInto == 0) ||
							(!atEnd && insertedInto == resultsArray.length)){
							// if it is at the end of the page, assume it goes into the prev or next page
							insertedInto = -1;
						}else{*/
							//resultsArray.splice(insertedInto, 0, changed); // and insert into the results array with the correct index
						//}
					}
				}else if(changed){
					// we don't have a queryEngine, so we can't provide any information
					// about where it was inserted or moved to. If it is an update, we leave it's position alone, other we at least indicate a new object
					if(existingId !== undef){
						// an update, keep the index the same
						insertedInto = removedFrom;
					}else /*if(!options.start)*/{
						// a new object
						insertedInto = store.defaultIndex || 0;
					}
					resultsArray.splice(insertedInto, 0, changed);
				}
				if(insertedInto > -1){
					// splice insertion arguments
					listener(insertedInto, 0, changed);
				}
/*					if((removedFrom > -1 || insertedInto > -1) &&
						(!excludeObjectUpdates || !queryExecutor || (removedFrom != insertedInto))){
				}*/
			});
		});

		return observed;
	},
	// a Comet driven store could directly call notify to notify observers when data has
	// changed on the backend
	// create a new instance
	notify: function(object, existingId){
		revision++;
		var updaters = this.queryUpdaters.slice();
		for(var i = 0, l = updaters.length; i < l; i++){
			updaters[i](object, existingId);
		}
	}
});
});
<|endoftext|>


<commit_before>/*exported PixelImage*/
/*jslint bitwise: true*/
/** Create an image with access to individual pixels

    A pixel's color at (x,y) is determined through 2 indirections:

    - colormapIndex = pixelIndex[x,y]
    - paletteIndex = colorMaps[colormapIndex][x,y]
    - color = palette[paletteIndex]
    - red = color[0], green = color[1], blue = color[2]

    Pixels are indexed:
    - index at (x,y) undefined -> transparant
    - index at (x,y) = number -> number of colormap in which color is stored at (x,y)

    Colormaps contain a mapping from (x,y) to an index in the palette.

http://csdb.dk/forums/?roomid=11&topicid=21409&showallposts=1

http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/

http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT

*/

var ColorMap = require('./ColorMap.js');
var PixelCalculator = require('./PixelCalculator.js');

function PixelImage(width, height, pWidth, pHeight) {
    'use strict';
    // public properties
    this.width = width;
    this.height = height;
    this.pWidth = pWidth === undefined ? 1 : pWidth; // aspect width of one pixel
    this.pHeight = pHeight === undefined ? 1 : pHeight; // aspect height of one pixel
    this.colorMaps = []; // maps x,y to a color
    this.palette = undefined; // the palette for all colors used in this image
    this.pixelIndex = []; // maps pixel x,y to a colormap
    this.ditherOffset = []; // offset for dithering used when mapping color
    this.dither = [
        [0]
    ]; // n x n bayer matrix for ordered dithering
    this.errorDiffusionDither = function() {};

    // weight per pixel channel (RGB or YUV) when calculating distance
    // [1, 1, 1] is equal weight, [1, 0, 0] in combination with YUV is phychedelic mode
    this.mappingWeight = [1, 1, 1];

}

PixelImage.prototype.assertValid = function() {
    'use strict';
    if (this.width === undefined ||this.height === undefined) {
        throw new Error('PixelImage has undefined dimensions.');
    }
};

/**
 * Find a color index at a specific coordinate in one of the color maps.
 * Returns the first match it finds, or undefined if no color maps contain the color index at the coordinate.
 * @param {int} x X coordinate
 * @param {int} y Y coordinate
 * @returns {int} Color index to find
 */
PixelImage.prototype.findColorInMap = function(x, y, color) {
    'use strict';
    var i;

    for (i = 0; i < this.colorMaps.length; i += 1) {
        if (color === this.colorMaps[i].getColor(x, y)) {
            return i;
        }
    }

    return undefined;
};

/**
 * Map a pixel to the closest available Colormap.
 * @param {int} x X coordinate
 * @param {int} y Y coordinate
 * @returns {int} Colormap index for the closest Colormap
 */
PixelImage.prototype.map = function(pixel, x, y, offsetPixel) {
    'use strict';
    var i,
        d,
        minVal,
        minI = 0,
        other;

    // determine closest pixel in palette (ignoring alpha)
    for (i = 0; i < this.colorMaps.length; i += 1) {
        other = this.colorMaps[i].getColor(x, y);
        d = this.palette.getDistance(pixel, other, offsetPixel, this.mappingWeight);
        if (minVal === undefined || d < minVal) {
            minVal = d;
            minI = i;
        }
    }

    return minI;

};

PixelImage.prototype.setPixelIndex = function s(x, y, index) {
    'use strict';
    if (this.pixelIndex[y] === undefined) {
        this.pixelIndex[y] = [];
    }
    this.pixelIndex[y][x] = index;
};

PixelImage.prototype.getPixelIndex = function(x, y) {
    'use strict';
    var row = this.pixelIndex[y];
    return row !== undefined ? row[x] : undefined;
};

PixelImage.prototype.setDitherOffset = function(x, y, offsetPixel) {
    'use strict';
    if (x < this.width && y < this.height) {
        if (this.ditherOffset[y] === undefined) {
            this.ditherOffset[y] = [];
        }
        this.ditherOffset[y][x] = offsetPixel;
    }
};

PixelImage.prototype.addDitherOffset = function(x, y, offsetPixel) {
    'use strict';
    var currentOffset = this.getDitherOffset(x, y);
    this.setDitherOffset(x, y, PixelCalculator.add(currentOffset, offsetPixel));
};

PixelImage.prototype.getDitherOffset = function(x, y) {
    'use strict';
    var row = this.ditherOffset[y];
    if (row !== undefined && row[x] !== undefined) {
        return row[x];
    }
    return PixelCalculator.emptyPixel;
};

PixelImage.prototype.orderedDither = function(x, y) {
    'use strict';
    var offset = this.dither[y % this.dither.length][x % this.dither.length];
    this.addDitherOffset(x + 1, y, [offset, offset, offset]);
};

/**
 * Set the value for a particular pixel.
 * @param {number} x - x coordinate
 * @param {number} y - y coordinate
 * @param {Array} pixel - Pixel values [r, g, b, a]
 */
PixelImage.prototype.poke = function(x, y, pixel) {
    'use strict';

    var mappedIndex,
        mappedPixel,
        colorMap,
        offsetPixel,
        error;

    offsetPixel = this.getDitherOffset(x, y);

    // map to closest color in palette
    mappedIndex = this.palette.mapPixel(pixel, offsetPixel, this.mappingWeight);

    // use the error for dithering
    mappedPixel = this.palette.get(mappedIndex);
    error = PixelCalculator.substract(mappedPixel, pixel);
    this.orderedDither(x, y, pixel);
    this.errorDiffusionDither(this, x, y, error);

    // try to reuse existing color map
    colorMap = this.findColorInMap(x, y, mappedIndex);

    // else see if there is there is a map with an empty pixel
    if (colorMap === undefined) {
        colorMap = this.findColorInMap(x, y, undefined);
    }

    if (colorMap !== undefined) {
        this.colorMaps[colorMap].add(x, y, mappedIndex);
    } else {
        // if all else fails, map to closest existing color
        if (colorMap === undefined) {
            colorMap = this.map(pixel, x, y, offsetPixel);
        }
    }

    this.setPixelIndex(x, y, colorMap);

};

PixelImage.prototype.drawImageData = function(imageData) {
    'use strict';
    var x,
        y,
        pixel;

    for (y = 0; y < this.height; y += 1) {
        for (x = 0; x < this.width; x += 1) {
            pixel = PixelCalculator.peek(imageData, x, y);
            this.poke(x, y, pixel);
        }
    }
};

PixelImage.prototype.fromImageData = function(imageData) {
    'use strict';
    this.init(imageData.width, imageData.height);
    this.colorMaps = [new ColorMap(this.width, this.height, 1, 1)];
    this.drawImageData(imageData);
};

PixelImage.prototype.getPaletteIndex = function(x, y) {
    'use strict';
    var ci = this.getPixelIndex(x, y);
    return ci !== undefined ? this.colorMaps[ci].getColor(x, y) : undefined;

};

/**
 * Get the value of a particular pixel.
 * @param {int} x X coordinate
 * @param {int} y Y coordinate
 * @returns {Array} Pixel values [r, g, b, a], or an empty pixel if x and y are out of range.
 */
PixelImage.prototype.peek = function(x, y) {
    'use strict';
    var paletteIndex = this.getPaletteIndex(x, y);
    return paletteIndex !== undefined ? this.palette.get(paletteIndex) : PixelImage.emptyPixel;
};

/*
PixelImage.prototype.toSrcUrl = function() {
    'use strict';
    this.assertValid();
    return this.toUrl('image/png');
};

PixelImage.prototype.toDownloadUrl = function() {
    'use strict';
    return this.toSrcUrl().replace('data:image/png', 'data:image/octet-stream');
};

PixelImage.prototype.toUrl = function(mimetype) {
    'use strict';
    var canvas = document.createElement('canvas'),
        context = canvas.getContext('2d'),
        imageData,
        x,
        y,
        px,
        py,
        xx,
        yy,
        pixel;

    canvas.width = this.width * this.pWidth;
    canvas.height = this.height * this.pHeight;
    imageData = context.createImageData(canvas.width, canvas.height);

    for (x = 0; x < this.width; x += 1) {
        for (y = 0; y < this.height; y += 1) {

            pixel = this.peek(x, y);
            for (px = 0; px < this.pWidth; px += 1) {
                xx = x * this.pWidth + px;
                yy = y * this.pHeight;
                for (py = 0; py < this.pHeight; py += 1) {
                    PixelCalculator.poke(imageData, xx, yy + py, pixel);
                }
            }
        }
    }

    context.putImageData(imageData, 0, 0);
    return canvas.toDataURL(mimetype);
};
*/
PixelImage.prototype.addColorMap = function(colorMap) {
    'use strict';
    this.colorMaps.push(colorMap);
};

PixelImage.prototype.getTransparencyPercentage = function() {
    'use strict';
    var x, y, count = 0;

    for (x = 0; x < this.width; x += 1) {
        for (y = 0; y < this.height; y += 1) {
            count += this.getPixelIndex(x, y) === undefined ? 1 : 0;
        }
    }

    return Math.round((100 * count) / (this.width * this.height));
};

module.exports = PixelImage;
<commit_msg>Refactoring PixelImage<commit_after>/*exported PixelImage*/
/*jslint bitwise: true*/
/** Create an image with access to individual pixels

    A pixel's color at (x,y) is determined through 2 indirections:

    - colormapIndex = pixelIndex[x,y]
    - paletteIndex = colorMaps[colormapIndex][x,y]
    - color = palette[paletteIndex]
    - red = color[0], green = color[1], blue = color[2]

    Pixels are indexed:
    - index at (x,y) undefined -> transparant
    - index at (x,y) = number -> number of colormap in which color is stored at (x,y)

    Colormaps contain a mapping from (x,y) to an index in the palette.

http://csdb.dk/forums/?roomid=11&topicid=21409&showallposts=1

http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/

http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT

*/

var ColorMap = require('./ColorMap.js');
var PixelCalculator = require('./PixelCalculator.js');

function PixelImage(width, height, pWidth, pHeight) {
    'use strict';
    // public properties
    this.width = width;
    this.height = height;
    this.pWidth = pWidth === undefined ? 1 : pWidth; // aspect width of one pixel
    this.pHeight = pHeight === undefined ? 1 : pHeight; // aspect height of one pixel
    this.colorMaps = []; // maps x,y to a color
    this.palette = undefined; // the palette for all colors used in this image
    var pixelIndex = []; // maps pixel x,y to a colormap
    this.ditherOffset = []; // offset for dithering used when mapping color
    this.dither = [
        [0]
    ]; // n x n bayer matrix for ordered dithering
    this.errorDiffusionDither = function() {};

    // weight per pixel channel (RGB or YUV) when calculating distance
    // [1, 1, 1] is equal weight, [1, 0, 0] in combination with YUV is phychedelic mode
    this.mappingWeight = [1, 1, 1];

    var that = this;

    var findColorInMap = function(x, y, color) {
        for (var i = 0; i < that.colorMaps.length; i += 1) {
            if (color === that.colorMaps[i].getColor(x, y)) {
                return i;
            }
        }
        return undefined;
    };

    /**
     * Map a pixel to the closest available Colormap.
     * @param {int} x X coordinate
     * @param {int} y Y coordinate
     * @returns {int} Colormap index for the closest Colormap
     */
    var map = function(pixel, x, y, offsetPixel) {

        var i,
            d,
            minVal,
            minI = 0,
            other;

        // determine closest pixel in palette (ignoring alpha)
        for (i = 0; i < that.colorMaps.length; i += 1) {
            other = that.colorMaps[i].getColor(x, y);
            d = that.palette.getDistance(pixel, other, offsetPixel, that.mappingWeight);
            if (minVal === undefined || d < minVal) {
                minVal = d;
                minI = i;
            }
        }

        return minI;

    };

    var setPixelIndex = function s(x, y, index) {
        if (pixelIndex[y] === undefined) {
            pixelIndex[y] = [];
        }
        pixelIndex[y][x] = index;
    };

    var getPixelIndex = function(x, y) {
        var row = pixelIndex[y];
        return row !== undefined ? row[x] : undefined;
    };

    var getPaletteIndex = function(x, y) {
        var ci = getPixelIndex(x, y);
        return ci !== undefined ? that.colorMaps[ci].getColor(x, y) : undefined;
    };

    /**
     * Set the value for a particular pixel.
     * @param {number} x - x coordinate
     * @param {number} y - y coordinate
     * @param {Array} pixel - Pixel values [r, g, b, a]
     */
    this.poke = function(x, y, pixel) {

        var mappedIndex,
            mappedPixel,
            colorMap,
            offsetPixel,
            error;

        offsetPixel = this.getDitherOffset(x, y);

        // map to closest color in palette
        mappedIndex = this.palette.mapPixel(pixel, offsetPixel, this.mappingWeight);

        // use the error for dithering
        mappedPixel = this.palette.get(mappedIndex);
        error = PixelCalculator.substract(mappedPixel, pixel);
        this.orderedDither(x, y, pixel);
        this.errorDiffusionDither(this, x, y, error);

        // try to reuse existing color map
        colorMap = findColorInMap(x, y, mappedIndex);

        // else see if there is there is a map with an empty pixel
        if (colorMap === undefined) {
            colorMap = findColorInMap(x, y, undefined);
        }

        if (colorMap !== undefined) {
            this.colorMaps[colorMap].add(x, y, mappedIndex);
        } else {
            // if all else fails, map to closest existing color
            if (colorMap === undefined) {
                colorMap = map(pixel, x, y, offsetPixel);
            }
        }

        setPixelIndex(x, y, colorMap);

    };

    /**
     * Get the value of a particular pixel.
     * @param {int} x X coordinate
     * @param {int} y Y coordinate
     * @returns {Array} Pixel values [r, g, b, a], or an empty pixel if x and y are out of range.
     */
    this.peek = function(x, y) {
        var paletteIndex = getPaletteIndex(x, y);
        return paletteIndex !== undefined ? this.palette.get(paletteIndex) : PixelImage.emptyPixel;
    };

}

PixelImage.prototype.assertValid = function() {
    'use strict';
    if (this.width === undefined || this.height === undefined) {
        throw new Error('PixelImage has undefined dimensions.');
    }
};

PixelImage.prototype.setDitherOffset = function(x, y, offsetPixel) {
    'use strict';
    if (x < this.width && y < this.height) {
        if (this.ditherOffset[y] === undefined) {
            this.ditherOffset[y] = [];
        }
        this.ditherOffset[y][x] = offsetPixel;
    }
};

PixelImage.prototype.addDitherOffset = function(x, y, offsetPixel) {
    'use strict';
    var currentOffset = this.getDitherOffset(x, y);
    this.setDitherOffset(x, y, PixelCalculator.add(currentOffset, offsetPixel));
};

PixelImage.prototype.getDitherOffset = function(x, y) {
    'use strict';
    var row = this.ditherOffset[y];
    if (row !== undefined && row[x] !== undefined) {
        return row[x];
    }
    return PixelCalculator.emptyPixel;
};

PixelImage.prototype.orderedDither = function(x, y) {
    'use strict';
    var offset = this.dither[y % this.dither.length][x % this.dither.length];
    this.addDitherOffset(x + 1, y, [offset, offset, offset]);
};

PixelImage.prototype.drawImageData = function(imageData) {
    'use strict';
    var x,
        y,
        pixel;

    for (y = 0; y < this.height; y += 1) {
        for (x = 0; x < this.width; x += 1) {
            pixel = PixelCalculator.peek(imageData, x, y);
            this.poke(x, y, pixel);
        }
    }
};

PixelImage.prototype.fromImageData = function(imageData) {
    'use strict';
    this.init(imageData.width, imageData.height);
    this.colorMaps = [new ColorMap(this.width, this.height, 1, 1)];
    this.drawImageData(imageData);
};

PixelImage.prototype.addColorMap = function(colorMap) {
    'use strict';
    this.colorMaps.push(colorMap);
};

module.exports = PixelImage;
<|endoftext|>


<commit_before>
function ProgressHR() {
    var progressItems = document.getElementsByClassName("ProgressHR");
    console.log("There are " + progressItems.length + " ProgressItem(s)");
    var hrs = document.getElementsByTagName('hr');
    console.log("There are " + hrs.length + " HR tags.");
    Debug.write("this is being debugged");

    for (var i = 0; i < progressItems.length; i++) {
        var article = progressItems[i];

        var totalLength = article.innerHTML.length;
        var contentLength = article.textContent.length;
        var blackSpaceLength = article.textContent.replace(/\s/g, '').length;
        console.log("Total length: " + totalLength);
        console.log("textContent Length: " + contentLength);
        console.log("Blackspace Length: " + blackSpaceLength);

        var itemHrs = [];
        var cumulativeLengths = [];
        var percentages = [];
        var cumulativeLength = 0;

        // bad perf here in a 'big' page
        for (var j = 0; j < hrs.length; j++) {
            if (hrs[j].parentNode === article) {
                console.log("child HR");
                itemHrs.push(hrs[j]);
            } else {
                console.log("not a child HR");
            }
        }
        console.log("There are " + itemHrs.length + " sections.");

        var hrIndex = 0;
        for (var j = 0; j < article.childNodes.length; j++) {
            if (article.childNodes[j] === itemHrs[hrIndex]) {
                cumulativeLengths.push(cumulativeLength);
                percentages.push(cumulativeLength / blackSpaceLength);
                console.log("Section " + hrIndex + " has length: " + cumulativeLength +
                    ", " + (100 * percentages[hrIndex]) + "%.");
                hrIndex++;
            }
            else {
                cumulativeLength += article.childNodes[j].textContent.replace(/\s/g,'').length;
            }
        }

        console.log("There are " + itemHrs.length + " HRs in this item.");
    }
};<commit_msg>removing some dead code<commit_after>
function ProgressHR() {
    var progressItems = document.getElementsByClassName("ProgressHR");
    console.log("There are " + progressItems.length + " ProgressItem(s)");
    var hrs = document.getElementsByTagName('hr');
    console.log("There are " + hrs.length + " HR tags.");
    Debug.write("this is being debugged");

    for (var i = 0; i < progressItems.length; i++) {
        var article = progressItems[i];

        var blackSpaceLength = article.textContent.replace(/\s/g, '').length;
        console.log("Blackspace Length: " + blackSpaceLength);

        var itemHrs = [];
        var cumulativeLengths = [];
        var percentages = [];
        var cumulativeLength = 0;

        // bad perf here in a 'big' page
        for (var j = 0; j < hrs.length; j++) {
            if (hrs[j].parentNode === article) {
                console.log("child HR");
                itemHrs.push(hrs[j]);
            } else {
                console.log("not a child HR");
            }
        }
        console.log("There are " + itemHrs.length + " sections.");

        var hrIndex = 0;
        for (var j = 0; j < article.childNodes.length; j++) {
            if (article.childNodes[j] === itemHrs[hrIndex]) {
                cumulativeLengths.push(cumulativeLength);
                percentages.push(cumulativeLength / blackSpaceLength);
                console.log("Section " + hrIndex + " has length: " + cumulativeLength +
                    ", " + (100 * percentages[hrIndex]) + "%.");
                hrIndex++;
            }
            else {
                cumulativeLength += article.childNodes[j].textContent.replace(/\s/g,'').length;
            }
        }

        console.log("There are " + itemHrs.length + " HRs in this item.");
    }
};<|endoftext|>


<commit_before>/**
* This class handles LZW encoding
* Adapted from Jef Poskanzer's Java port by way of J. M. G. Elliott.
* @author Kevin Weiner (original Java version - kweiner@fmsware.com)
* @author Thibault Imbert (AS3 version - bytearray.org)
* @version 0.1 AS3 implementation
*/

	//import flash.utils.ByteArray;

	LZWEncoder = function()
	{
	    var exports = {};
		/*private_static*/ var EOF/*int*/ = -1;
		/*private*/ var imgW/*int*/;
		/*private*/ var imgH/*int*/
		/*private*/ var pixAry/*ByteArray*/;
		/*private*/ var initCodeSize/*int*/;
		/*private*/ var remaining/*int*/;
		/*private*/ var curPixel/*int*/;

		// GIFCOMPR.C - GIF Image compression routines
		// Lempel-Ziv compression based on 'compress'. GIF modifications by
		// David Rowley (mgardi@watdcsu.waterloo.edu)
		// General DEFINEs

		/*private_static*/ var BITS/*int*/ = 12;
		/*private_static*/ var HSIZE/*int*/ = 5003; // 80% occupancy

		// GIF Image compression - modified 'compress'
		// Based on: compress.c - File compression ala IEEE Computer, June 1984.
		// By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
		// Jim McKie (decvax!mcvax!jim)
		// Steve Davies (decvax!vax135!petsd!peora!srd)
		// Ken Turkowski (decvax!decwrl!turtlevax!ken)
		// James A. Woods (decvax!ihnp4!ames!jaw)
		// Joe Orost (decvax!vax135!petsd!joe)

		/*private*/ var n_bits/*int*/ // number of bits/code
		/*private*/ var maxbits/*int*/ = BITS; // user settable max # bits/code
		/*private*/ var maxcode/*int*/ // maximum code, given n_bits
		/*private*/ var maxmaxcode/*int*/ = 1 << BITS; // should NEVER generate this code
		/*private*/ var htab/*Array*/ = new Array;
		/*private*/ var codetab/*Array*/ = new Array;
		/*private*/ var hsize/*int*/ = HSIZE; // for dynamic table sizing
		/*private*/ var free_ent/*int*/ = 0; // first unused entry

		// block compression parameters -- after all codes are used up,
		// and compression rate changes, start over.

		/*private*/ var clear_flg/*Boolean*/ = false;

		// Algorithm: use open addressing double hashing (no chaining) on the
		// prefix code / next character combination. We do a variant of Knuth's
		// algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
		// secondary probe. Here, the modular division first probe is gives way
		// to a faster exclusive-or manipulation. Also do block compression with
		// an adaptive reset, whereby the code table is cleared when the compression
		// ratio decreases, but after the table fills. The variable-length output
		// codes are re-sized at this point, and a special CLEAR code is generated
		// for the decompressor. Late addition: construct the table according to
		// file size for noticeable speed improvement on small files. Please direct
		// questions about this implementation to ames!jaw.

		/*private*/ var g_init_bits/*int*/;
		/*private*/ var ClearCode/*int*/;
		/*private*/ var EOFCode/*int*/;

		// output
		// Output the given code.
		// Inputs:
		// code: A n_bits-bit integer. If == -1, then EOF. This assumes
		// that n_bits =< wordsize - 1.
		// Outputs:
		// Outputs code to the file.
		// Assumptions:
		// Chars are 8 bits long.
		// Algorithm:
		// Maintain a BITS character long buffer (so that 8 codes will
		// fit in it exactly). Use the VAX insv instruction to insert each
		// code in turn. When the buffer fills up empty it and start over.

		/*private*/ var cur_accum/*int*/ = 0;
		/*private*/ var cur_bits/*int*/ = 0;
		/*private*/ var masks/*Array*/ = [ 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF ];

		// Number of characters so far in this 'packet'
		/*private*/ var a_count/*int*/;

		// Define the storage for the packet accumulator
		/*private*/ var accum/*ByteArray*/ = [];

		var LZWEncoder = exports.LZWEncoder = function LZWEncoder (width/*int*/, height/*int*/, pixels/*ByteArray*/, color_depth/*int*/)
		{

			imgW = width;
			imgH = height;
			pixAry = pixels;
			initCodeSize = Math.max(2, color_depth);

		}

		// Add a character to the end of the current packet, and if it is 254
		// characters, flush the packet to disk.
		var char_out = function char_out(c/*Number*/, outs/*ByteArray*/)/*void*/
		{
			accum[a_count++] = c;
			if (a_count >= 254) flush_char(outs);

		}

		// Clear out the hash table
		// table clear for block compress

		var cl_block = function cl_block(outs/*ByteArray*/)/*void*/
		{

			cl_hash(hsize);
			free_ent = ClearCode + 2;
			clear_flg = true;
			output(ClearCode, outs);

		}

		// reset code table
		var cl_hash = function cl_hash(hsize/*int*/)/*void*/
		{

			for (var i/*int*/ = 0; i < hsize; ++i) htab[i] = -1;

		}

		var compress = exports.compress = function compress(init_bits/*int*/, outs/*ByteArray*/)/*void*/

		{
			var fcode/*int*/;
			var i/*int*/ /* = 0 */;
			var c/*int*/;
			var ent/*int*/;
			var disp/*int*/;
			var hsize_reg/*int*/;
			var hshift/*int*/;

			// Set up the globals: g_init_bits - initial number of bits
			g_init_bits = init_bits;

			// Set up the necessary values
			clear_flg = false;
			n_bits = g_init_bits;
			maxcode = MAXCODE(n_bits);

			ClearCode = 1 << (init_bits - 1);
			EOFCode = ClearCode + 1;
			free_ent = ClearCode + 2;

			a_count = 0; // clear packet

			ent = nextPixel();

			hshift = 0;
			for (fcode = hsize; fcode < 65536; fcode *= 2)
			  ++hshift;
			hshift = 8 - hshift; // set hash code range bound

			hsize_reg = hsize;
			cl_hash(hsize_reg); // clear hash table

			output(ClearCode, outs);

			outer_loop: while ((c = nextPixel()) != EOF)

			{

				fcode = (c << maxbits) + ent;
				i = (c << hshift) ^ ent; // xor hashing

				if (htab[i] == fcode)
				{
				ent = codetab[i];
				continue;
				} else if (htab[i] >= 0) // non-empty slot
				{
					disp = hsize_reg - i; // secondary hash (after G. Knott)
					if (i == 0)
					disp = 1;
					do
					{

						if ((i -= disp) < 0) i += hsize_reg;

						if (htab[i] == fcode)
						{
						ent = codetab[i];
						continue outer_loop;
						}
					} while (htab[i] >= 0);
				}

				output(ent, outs);
				ent = c;
				if (free_ent < maxmaxcode)
				{
					codetab[i] = free_ent++; // code -> hashtable
					htab[i] = fcode;
				} else cl_block(outs);
			}

			// Put out the final code.
			output(ent, outs);
			output(EOFCode, outs);

		}

		// ----------------------------------------------------------------------------
		var encode = exports.encode = function encode(os/*ByteArray*/)/*void*/
		{
			os.writeByte(initCodeSize); // write "initial code size" byte
			remaining = imgW * imgH; // reset navigation variables
			curPixel = 0;
			compress(initCodeSize + 1, os); // compress and write the pixel data
			os.writeByte(0); // write block terminator

		}

		// Flush the packet to disk, and reset the accumulator
		var flush_char = function flush_char(outs/*ByteArray*/)/*void*/
		{

			if (a_count > 0)
			{
				outs.writeByte(a_count);
				outs.writeBytes(accum, 0, a_count);
				a_count = 0;
			}

		}

		var MAXCODE = function MAXCODE(n_bits/*int*/)/*int*/
		{

			return (1 << n_bits) - 1;

		}

		// ----------------------------------------------------------------------------
		// Return the next pixel from the image
		// ----------------------------------------------------------------------------

		var nextPixel = function nextPixel()/*int*/
		{

			if (remaining == 0) return EOF;

			--remaining;

			var pix/*Number*/ = pixAry[curPixel++];

			return pix & 0xff;

		}

		var output = function output(code/*int*/, outs/*ByteArray*/)/*void*/

		{
			cur_accum &= masks[cur_bits];

			if (cur_bits > 0) cur_accum |= (code << cur_bits);
			else cur_accum = code;

			cur_bits += n_bits;

			while (cur_bits >= 8)

			{

				char_out((cur_accum & 0xff), outs);
				cur_accum >>= 8;
				cur_bits -= 8;

			}

			// If the next entry is going to be too big for the code size,
			// then increase it, if possible.

			if (free_ent > maxcode || clear_flg)
			{

				if (clear_flg)
				{

					maxcode = MAXCODE(n_bits = g_init_bits);
					clear_flg = false;

				} else
				{

					++n_bits;

					if (n_bits == maxbits) maxcode = maxmaxcode;

					else maxcode = MAXCODE(n_bits);

				}

			}

			if (code == EOFCode)
			{

				// At EOF, write the rest of the buffer.
				while (cur_bits > 0)
				{

					char_out((cur_accum & 0xff), outs);
					cur_accum >>= 8;
					cur_bits -= 8;
				}

				flush_char(outs);

			}

		}
		LZWEncoder.apply(this, arguments);
	   return exports;
	}

<commit_msg>Remove language-irrelevant dependency comment.<commit_after>/**
* This class handles LZW encoding
* Adapted from Jef Poskanzer's Java port by way of J. M. G. Elliott.
* @author Kevin Weiner (original Java version - kweiner@fmsware.com)
* @author Thibault Imbert (AS3 version - bytearray.org)
* @version 0.1 AS3 implementation
*/

	LZWEncoder = function()
	{
	    var exports = {};
		/*private_static*/ var EOF/*int*/ = -1;
		/*private*/ var imgW/*int*/;
		/*private*/ var imgH/*int*/
		/*private*/ var pixAry/*ByteArray*/;
		/*private*/ var initCodeSize/*int*/;
		/*private*/ var remaining/*int*/;
		/*private*/ var curPixel/*int*/;

		// GIFCOMPR.C - GIF Image compression routines
		// Lempel-Ziv compression based on 'compress'. GIF modifications by
		// David Rowley (mgardi@watdcsu.waterloo.edu)
		// General DEFINEs

		/*private_static*/ var BITS/*int*/ = 12;
		/*private_static*/ var HSIZE/*int*/ = 5003; // 80% occupancy

		// GIF Image compression - modified 'compress'
		// Based on: compress.c - File compression ala IEEE Computer, June 1984.
		// By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
		// Jim McKie (decvax!mcvax!jim)
		// Steve Davies (decvax!vax135!petsd!peora!srd)
		// Ken Turkowski (decvax!decwrl!turtlevax!ken)
		// James A. Woods (decvax!ihnp4!ames!jaw)
		// Joe Orost (decvax!vax135!petsd!joe)

		/*private*/ var n_bits/*int*/ // number of bits/code
		/*private*/ var maxbits/*int*/ = BITS; // user settable max # bits/code
		/*private*/ var maxcode/*int*/ // maximum code, given n_bits
		/*private*/ var maxmaxcode/*int*/ = 1 << BITS; // should NEVER generate this code
		/*private*/ var htab/*Array*/ = new Array;
		/*private*/ var codetab/*Array*/ = new Array;
		/*private*/ var hsize/*int*/ = HSIZE; // for dynamic table sizing
		/*private*/ var free_ent/*int*/ = 0; // first unused entry

		// block compression parameters -- after all codes are used up,
		// and compression rate changes, start over.

		/*private*/ var clear_flg/*Boolean*/ = false;

		// Algorithm: use open addressing double hashing (no chaining) on the
		// prefix code / next character combination. We do a variant of Knuth's
		// algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
		// secondary probe. Here, the modular division first probe is gives way
		// to a faster exclusive-or manipulation. Also do block compression with
		// an adaptive reset, whereby the code table is cleared when the compression
		// ratio decreases, but after the table fills. The variable-length output
		// codes are re-sized at this point, and a special CLEAR code is generated
		// for the decompressor. Late addition: construct the table according to
		// file size for noticeable speed improvement on small files. Please direct
		// questions about this implementation to ames!jaw.

		/*private*/ var g_init_bits/*int*/;
		/*private*/ var ClearCode/*int*/;
		/*private*/ var EOFCode/*int*/;

		// output
		// Output the given code.
		// Inputs:
		// code: A n_bits-bit integer. If == -1, then EOF. This assumes
		// that n_bits =< wordsize - 1.
		// Outputs:
		// Outputs code to the file.
		// Assumptions:
		// Chars are 8 bits long.
		// Algorithm:
		// Maintain a BITS character long buffer (so that 8 codes will
		// fit in it exactly). Use the VAX insv instruction to insert each
		// code in turn. When the buffer fills up empty it and start over.

		/*private*/ var cur_accum/*int*/ = 0;
		/*private*/ var cur_bits/*int*/ = 0;
		/*private*/ var masks/*Array*/ = [ 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF ];

		// Number of characters so far in this 'packet'
		/*private*/ var a_count/*int*/;

		// Define the storage for the packet accumulator
		/*private*/ var accum/*ByteArray*/ = [];

		var LZWEncoder = exports.LZWEncoder = function LZWEncoder (width/*int*/, height/*int*/, pixels/*ByteArray*/, color_depth/*int*/)
		{

			imgW = width;
			imgH = height;
			pixAry = pixels;
			initCodeSize = Math.max(2, color_depth);

		}

		// Add a character to the end of the current packet, and if it is 254
		// characters, flush the packet to disk.
		var char_out = function char_out(c/*Number*/, outs/*ByteArray*/)/*void*/
		{
			accum[a_count++] = c;
			if (a_count >= 254) flush_char(outs);

		}

		// Clear out the hash table
		// table clear for block compress

		var cl_block = function cl_block(outs/*ByteArray*/)/*void*/
		{

			cl_hash(hsize);
			free_ent = ClearCode + 2;
			clear_flg = true;
			output(ClearCode, outs);

		}

		// reset code table
		var cl_hash = function cl_hash(hsize/*int*/)/*void*/
		{

			for (var i/*int*/ = 0; i < hsize; ++i) htab[i] = -1;

		}

		var compress = exports.compress = function compress(init_bits/*int*/, outs/*ByteArray*/)/*void*/

		{
			var fcode/*int*/;
			var i/*int*/ /* = 0 */;
			var c/*int*/;
			var ent/*int*/;
			var disp/*int*/;
			var hsize_reg/*int*/;
			var hshift/*int*/;

			// Set up the globals: g_init_bits - initial number of bits
			g_init_bits = init_bits;

			// Set up the necessary values
			clear_flg = false;
			n_bits = g_init_bits;
			maxcode = MAXCODE(n_bits);

			ClearCode = 1 << (init_bits - 1);
			EOFCode = ClearCode + 1;
			free_ent = ClearCode + 2;

			a_count = 0; // clear packet

			ent = nextPixel();

			hshift = 0;
			for (fcode = hsize; fcode < 65536; fcode *= 2)
			  ++hshift;
			hshift = 8 - hshift; // set hash code range bound

			hsize_reg = hsize;
			cl_hash(hsize_reg); // clear hash table

			output(ClearCode, outs);

			outer_loop: while ((c = nextPixel()) != EOF)

			{

				fcode = (c << maxbits) + ent;
				i = (c << hshift) ^ ent; // xor hashing

				if (htab[i] == fcode)
				{
				ent = codetab[i];
				continue;
				} else if (htab[i] >= 0) // non-empty slot
				{
					disp = hsize_reg - i; // secondary hash (after G. Knott)
					if (i == 0)
					disp = 1;
					do
					{

						if ((i -= disp) < 0) i += hsize_reg;

						if (htab[i] == fcode)
						{
						ent = codetab[i];
						continue outer_loop;
						}
					} while (htab[i] >= 0);
				}

				output(ent, outs);
				ent = c;
				if (free_ent < maxmaxcode)
				{
					codetab[i] = free_ent++; // code -> hashtable
					htab[i] = fcode;
				} else cl_block(outs);
			}

			// Put out the final code.
			output(ent, outs);
			output(EOFCode, outs);

		}

		// ----------------------------------------------------------------------------
		var encode = exports.encode = function encode(os/*ByteArray*/)/*void*/
		{
			os.writeByte(initCodeSize); // write "initial code size" byte
			remaining = imgW * imgH; // reset navigation variables
			curPixel = 0;
			compress(initCodeSize + 1, os); // compress and write the pixel data
			os.writeByte(0); // write block terminator

		}

		// Flush the packet to disk, and reset the accumulator
		var flush_char = function flush_char(outs/*ByteArray*/)/*void*/
		{

			if (a_count > 0)
			{
				outs.writeByte(a_count);
				outs.writeBytes(accum, 0, a_count);
				a_count = 0;
			}

		}

		var MAXCODE = function MAXCODE(n_bits/*int*/)/*int*/
		{

			return (1 << n_bits) - 1;

		}

		// ----------------------------------------------------------------------------
		// Return the next pixel from the image
		// ----------------------------------------------------------------------------

		var nextPixel = function nextPixel()/*int*/
		{

			if (remaining == 0) return EOF;

			--remaining;

			var pix/*Number*/ = pixAry[curPixel++];

			return pix & 0xff;

		}

		var output = function output(code/*int*/, outs/*ByteArray*/)/*void*/

		{
			cur_accum &= masks[cur_bits];

			if (cur_bits > 0) cur_accum |= (code << cur_bits);
			else cur_accum = code;

			cur_bits += n_bits;

			while (cur_bits >= 8)

			{

				char_out((cur_accum & 0xff), outs);
				cur_accum >>= 8;
				cur_bits -= 8;

			}

			// If the next entry is going to be too big for the code size,
			// then increase it, if possible.

			if (free_ent > maxcode || clear_flg)
			{

				if (clear_flg)
				{

					maxcode = MAXCODE(n_bits = g_init_bits);
					clear_flg = false;

				} else
				{

					++n_bits;

					if (n_bits == maxbits) maxcode = maxmaxcode;

					else maxcode = MAXCODE(n_bits);

				}

			}

			if (code == EOFCode)
			{

				// At EOF, write the rest of the buffer.
				while (cur_bits > 0)
				{

					char_out((cur_accum & 0xff), outs);
					cur_accum >>= 8;
					cur_bits -= 8;
				}

				flush_char(outs);

			}

		}
		LZWEncoder.apply(this, arguments);
	   return exports;
	}

<|endoftext|>