<commit_before>// --------------------------------------------------------------------------------------------------------------------
//
// glacier.js - class for AWS Glacier
//
// Copyright (c) 2011, 2012 AppsAttic Ltd - http://www.appsattic.com/
// Written by Andrew Chilton <chilts@appsattic.com>
//
// License: http://opensource.org/licenses/MIT
//
// --------------------------------------------------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------
// requires

// built-ins
var util = require('util');

// dependencies
var _ = require('underscore');

// our own
var awssum = require('awssum');
var amazon = require('awssum-amazon');
var operations = require('./config.js');
var awsSignatureV4 = require('awssum-amazon/lib/aws-signature-v4');

// --------------------------------------------------------------------------------------------------------------------
// package variables

var MARK = 'glacier: ';

// From: http://docs.amazonwebservices.com/general/latest/gr/rande.html
var endPoint = {};
endPoint[amazon.US_EAST_1]      = "glacier.us-east-1.amazonaws.com";
endPoint[amazon.US_WEST_1]      = "glacier.us-west-1.amazonaws.com";
endPoint[amazon.US_WEST_2]      = "glacier.us-west-2.amazonaws.com";
endPoint[amazon.EU_WEST_1]      = "glacier.eu-west-1.amazonaws.com";
// endPoint[amazon.AP_SOUTHEAST_1] = "";
endPoint[amazon.AP_NORTHEAST_1] = "glacier.ap-northeast-1.amazonaws.com";
// endPoint[amazon.SA_EAST_1]      = "";
// endPoint[amazon.US_GOV_WEST_1]  = "";

var version = '2012-06-01';

// --------------------------------------------------------------------------------------------------------------------
// constructor

var Glacier = function(opts) {
    var self = this;

    // call the superclass for initialisation
    Glacier.super_.call(this, opts);

    // check the region is valid
    if ( ! endPoint[opts.region] ) {
        throw MARK + "invalid region '" + opts.region + "'";
    }

    return self;
};

// inherit from Amazon
util.inherits(Glacier, amazon.Amazon);

// --------------------------------------------------------------------------------------------------------------------
// methods we need to implement from awssum.js/amazon.js

Glacier.prototype.scope = function() {
    return 'glacier';
};

Glacier.prototype.serviceName = function() {
    return 'Glacier';
};

Glacier.prototype.needsTarget = function() {
    return false;
};

Glacier.prototype.host = function() {
    return endPoint[this.region()];
};

Glacier.prototype.version = function() {
    return version;
};

Glacier.prototype.extractBody = function() {
    return 'json';
};

// this service uses the AWS Signature v4
Glacier.prototype.strToSign        = awsSignatureV4.strToSign;
Glacier.prototype.signature        = awsSignatureV4.signature;
Glacier.prototype.addSignature     = awsSignatureV4.addSignature;
// Glacier.prototype.addCommonOptions = awsSignatureV4.addCommonOptions;
Glacier.prototype.contentType      = awsSignatureV4.contentType;
Glacier.prototype.addCommonOptions = function(options, args) {
    var self = this;

    // yes, Signature v4, but we also need this
    options.headers['x-amz-glacier-version'] = self.version();

    // now call the signature addCommonOptions
    awsSignatureV4.addCommonOptions.apply(self, [ options, args ]);
};

// --------------------------------------------------------------------------------------------------------------------
// operations on the service

_.each(operations, function(operation, operationName) {
    Glacier.prototype[operationName] = awssum.makeOperation(operation);
});

// --------------------------------------------------------------------------------------------------------------------
// exports

exports.Glacier = Glacier;

// --------------------------------------------------------------------------------------------------------------------
<commit_msg>Use the Amazon Signature V2<commit_after>// --------------------------------------------------------------------------------------------------------------------
//
// glacier.js - class for AWS Glacier
//
// Copyright (c) 2011, 2012 AppsAttic Ltd - http://www.appsattic.com/
// Written by Andrew Chilton <chilts@appsattic.com>
//
// License: http://opensource.org/licenses/MIT
//
// --------------------------------------------------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------
// requires

// built-ins
var util = require('util');

// dependencies
var _ = require('underscore');

// our own
var awssum = require('awssum');
var amazon = require('awssum-amazon');
var operations = require('./config.js');
var awsSignatureV4 = require('awssum-amazon/lib/aws-signature-v4');

// --------------------------------------------------------------------------------------------------------------------
// package variables

var MARK = 'glacier: ';

// From: http://docs.amazonwebservices.com/general/latest/gr/rande.html
var endPoint = {};
endPoint[amazon.US_EAST_1]      = "glacier.us-east-1.amazonaws.com";
endPoint[amazon.US_WEST_1]      = "glacier.us-west-1.amazonaws.com";
endPoint[amazon.US_WEST_2]      = "glacier.us-west-2.amazonaws.com";
endPoint[amazon.EU_WEST_1]      = "glacier.eu-west-1.amazonaws.com";
// endPoint[amazon.AP_SOUTHEAST_1] = "";
endPoint[amazon.AP_NORTHEAST_1] = "glacier.ap-northeast-1.amazonaws.com";
// endPoint[amazon.SA_EAST_1]      = "";
// endPoint[amazon.US_GOV_WEST_1]  = "";

var version = '2012-06-01';

// --------------------------------------------------------------------------------------------------------------------
// constructor

var Glacier = function(opts) {
    var self = this;

    // call the superclass for initialisation
    Glacier.super_.call(this, opts);

    // check the region is valid
    if ( ! endPoint[opts.region] ) {
        throw MARK + "invalid region '" + opts.region + "'";
    }

    return self;
};

// inherit from Amazon
util.inherits(Glacier, amazon.AmazonSignatureV2);

// --------------------------------------------------------------------------------------------------------------------
// methods we need to implement from awssum.js/amazon.js

Glacier.prototype.scope = function() {
    return 'glacier';
};

Glacier.prototype.serviceName = function() {
    return 'Glacier';
};

Glacier.prototype.needsTarget = function() {
    return false;
};

Glacier.prototype.host = function() {
    return endPoint[this.region()];
};

Glacier.prototype.version = function() {
    return version;
};

Glacier.prototype.extractBody = function() {
    return 'json';
};

// this service uses the AWS Signature v4
Glacier.prototype.strToSign        = awsSignatureV4.strToSign;
Glacier.prototype.signature        = awsSignatureV4.signature;
Glacier.prototype.addSignature     = awsSignatureV4.addSignature;
// Glacier.prototype.addCommonOptions = awsSignatureV4.addCommonOptions;
Glacier.prototype.contentType      = awsSignatureV4.contentType;
Glacier.prototype.addCommonOptions = function(options, args) {
    var self = this;

    // yes, Signature v4, but we also need this
    options.headers['x-amz-glacier-version'] = self.version();

    // now call the signature addCommonOptions
    awsSignatureV4.addCommonOptions.apply(self, [ options, args ]);
};

// --------------------------------------------------------------------------------------------------------------------
// operations on the service

_.each(operations, function(operation, operationName) {
    Glacier.prototype[operationName] = awssum.makeOperation(operation);
});

// --------------------------------------------------------------------------------------------------------------------
// exports

exports.Glacier = Glacier;

// --------------------------------------------------------------------------------------------------------------------
<|endoftext|>


<commit_before>import injectScript from 'core/injectscript';

/**
 * Resume paused angular execution
 */
export default function(){
	injectScript('angular.resumeBootstrap();');
};
<commit_msg>Emit connect if angular is too late for socket.io connect event<commit_after>import injectScript from 'core/injectscript';

/**
 * Resume paused angular execution
 */
export default function(){
	injectScript(`angular.resumeBootstrap();
	if(window.socket && window.socket.connected){
		window.socket.emit('connect');
	}`);
};
<|endoftext|>


<commit_before>/*
 *     Copyright (c) 2012-2013 CoNWeT Lab., Universidad Politécnica de Madrid
 *
 *     This file is part of Wirecloud Platform.
 *
 *     Wirecloud Platform is free software: you can redistribute it and/or
 *     modify it under the terms of the GNU Affero General Public License as
 *     published by the Free Software Foundation, either version 3 of the
 *     License, or (at your option) any later version.
 *
 *     Wirecloud is distributed in the hope that it will be useful, but WITHOUT
 *     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
 *     License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Wirecloud Platform.  If not, see
 *     <http://www.gnu.org/licenses/>.
 *
 */

/*global Wirecloud*/

(function (utils) {

    "use strict";

    var VERSION_RE = /^((?:[1-9]\d*\.|0\.)*(?:[1-9]\d*|0))((?:a|b|rc)[1-9]\d*)?$/;

    var Version = function Version(version, source) {
        var groups, msg;
        if (typeof version == 'string') {
            groups = version.match(VERSION_RE);
            if (groups == null) {
                msg = utils.gettext("%(version)s is not a valid version");
                throw new TypeError(utils.interpolate(msg, {version:version}));
            }
            this.array = groups[1].split('.').map(function (x) { return parseInt(x, 10); });
            this.pre_version = groups[2] != null ? groups[2] : null;
            this.dev = groups[3] != null;
            this.text = version;
        } else if (version instanceof Array) {
            this.array = version;
            this.pre_version = null;
            this.dev = false;
            this.text = version.join('.');
        } else {
            throw new TypeError(utils.gettext("missing or invalid version parameter"));
        }
        this.source = source;
        Object.freeze(this);
    };

    Version.prototype.compareTo = function compareTo(version) {
        var len, value1, value2, pre_version1, pre_version2, i;

        if (!(version instanceof Version)) {
            // Try to parse version
            try {
                version = Version(version);
            } catch (e) {
                throw new TypeError(utils.gettext("invalid version parameter"));
            }
        }

        len = Math.max(this.array.length, version.array.length);

        for (i = 0; i < len; i += 1) {
            value1 = this.array[i] != null ? this.array[i] : 0;
            value2 = version.array[i] != null ? version.array[i] : 0;

            if (value1 !== value2) {
                return value1 - value2;
            }
        }

        pre_version1 = this.pre_version;
        if (pre_version1 == null) {
            pre_version1 = "z";
        }
        pre_version2 = version.pre_version;
        if (pre_version2 == null) {
            pre_version2 = "z";
        }

        if (pre_version1 < pre_version2) {
            return -1;
        } else if (pre_version1 > pre_version2) {
            return 1;
        } else {
            // If neither or both are dev return 0 (equals)
            if (this.dev === version.dev) {
                return 0;
            } else {
                // Development versions are lower
                return this.dev ? -1 : 1;
            }
        }
    };

    Version.prototype.toString = function toString() {
        return this.text;
    };

    Wirecloud.Version = Version;

})(Wirecloud.Utils);
<commit_msg>Fix frontend version regex changes from previous commit<commit_after>/*
 *     Copyright (c) 2012-2013 CoNWeT Lab., Universidad Politécnica de Madrid
 *
 *     This file is part of Wirecloud Platform.
 *
 *     Wirecloud Platform is free software: you can redistribute it and/or
 *     modify it under the terms of the GNU Affero General Public License as
 *     published by the Free Software Foundation, either version 3 of the
 *     License, or (at your option) any later version.
 *
 *     Wirecloud is distributed in the hope that it will be useful, but WITHOUT
 *     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
 *     License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Wirecloud Platform.  If not, see
 *     <http://www.gnu.org/licenses/>.
 *
 */

/*global Wirecloud*/

(function (utils) {

    "use strict";

    var VERSION_RE = /^((?:[1-9]\d*\.|0\.)*(?:[1-9]\d*|0))((?:a|b|rc)[1-9]\d*)?(-dev.*)?$/; // Hangs if it doesn't match the RE

    var Version = function Version(version, source) {
        var groups, msg;
        if (typeof version == 'string') {
            groups = version.match(VERSION_RE);
            if (groups == null) {
                msg = utils.gettext("%(version)s is not a valid version");
                throw new TypeError(utils.interpolate(msg, {version:version}));
            }
            this.array = groups[1].split('.').map(function (x) { return parseInt(x, 10); });
            this.pre_version = groups[2] != null ? groups[2] : null;
            this.dev = groups[3] != null;
            this.text = version;
        } else if (version instanceof Array) {
            this.array = version;
            this.pre_version = null;
            this.dev = false;
            this.text = version.join('.');
        } else {
            throw new TypeError(utils.gettext("missing or invalid version parameter"));
        }
        this.source = source;
        Object.freeze(this);
    };

    Version.prototype.compareTo = function compareTo(version) {
        var len, value1, value2, pre_version1, pre_version2, i;

        if (!(version instanceof Version)) {
            // Try to parse version
            try {
                version = Version(version);
            } catch (e) {
                throw new TypeError(utils.gettext("invalid version parameter"));
            }
        }

        len = Math.max(this.array.length, version.array.length);

        for (i = 0; i < len; i += 1) {
            value1 = this.array[i] != null ? this.array[i] : 0;
            value2 = version.array[i] != null ? version.array[i] : 0;

            if (value1 !== value2) {
                return value1 - value2;
            }
        }

        pre_version1 = this.pre_version;
        if (pre_version1 == null) {
            pre_version1 = "z";
        }
        pre_version2 = version.pre_version;
        if (pre_version2 == null) {
            pre_version2 = "z";
        }

        if (pre_version1 < pre_version2) {
            return -1;
        } else if (pre_version1 > pre_version2) {
            return 1;
        } else {
            // If neither or both are dev return 0 (equals)
            if (this.dev === version.dev) {
                return 0;
            } else {
                // Development versions are lower
                return this.dev ? -1 : 1;
            }
        }
    };

    Version.prototype.toString = function toString() {
        return this.text;
    };

    Wirecloud.Version = Version;

})(Wirecloud.Utils);
<|endoftext|>


<commit_before>var HeaderWidget = (function() {

  var render = function() {
    var conf = $.getConfig();
    var tpl = $.getTemplate("widgets/zbase-header", "zbase_header_tpl");

    $(".userid_info", tpl).innerHTML = conf.current_user.userid;
    $(".namespace_info", tpl).innerHTML = conf.current_user.namespace;

    $(".change_namespace", tpl).addEventListener("click", showSelectNamespacePopup);
    $.onClick($(".dropdown", tpl), toggleDropdown);
    $("z-search", tpl).addEventListener("z-search-autocomplete", searchAutocomplete);
    $("z-search", tpl).addEventListener("z-search-submit", searchSubmit);
    $("z-dropdown.new_query", tpl).addEventListener("change", createNewDocument);

    var elem = $("#zbase_header");
    $.replaceContent(elem, tpl);
    elem.classList.remove("hidden");

    document.addEventListener("click", function(event) {
      if ((function getParentWithClass(el, className) {
        while ((el = el.parentElement) && !el.classList.contains(className));
        return el;
      })(event.target, "dropdown")) return;

      $(".dropdown", elem).classList.remove("open");
    });

    $.handleLinks(elem);
  };

  var update = function(path) {
    var elem = $("#zbase_header");
    var input = $("z-search input", elem);

    if (path.indexOf("/a/search") > -1) {
      var qparam = UrlUtil.getParamValue(path, "q");
      if (qparam != null) {
        input.value = qparam;
        return;
      }
    }

    input.value = "";
    /*
    var items = elem.querySelectorAll(".nav");
    var prev_active_item = $(".nav.active", elem);
    var active_item;

    if (prev_active_item) {
      prev_active_item.classList.remove("active");
    }

    for (var i = 0; i < items.length; i++) {
      if (path.indexOf(items[i].getAttribute("href")) == 0) {
        active_item = items[i];
      }
    }

    if (active_item) {
      active_item.classList.add("active");
    }*/
  };

  var toggleDropdown = function() {
    this.classList.toggle("open");
  };

  var showSelectNamespacePopup = function() {
    ZBase.showLoader();
    ZBase.loadModules(["widgets/z-modal"], function() {
      var tpl = $.getTemplate(
          "widgets/zbase-header",
          "zbase_header_namespace_prompt_tpl");
      var modal = $("z-modal", tpl);
      document.body.appendChild(modal);

      modal.addEventListener("z-modal-close", function() {
        document.body.removeChild(modal);
      });

      var list = modal.querySelector(".namespace_list");
      list.innerHTML = "";

      $.httpGet("/api/v1/auth/available_namespaces", function(res) {
        // Replace with parsing of actual response.
        res = ["namespace1", "namespace2", "namespace3"];

        res.forEach(function(namespace) {
          var namespaceElem = document.createElement("li");
          namespaceElem.setAttribute("data-namespace", namespace);
          namespaceElem.innerHTML = namespace;
          namespaceElem.addEventListener("click", (function(namespace) {
            return function() {
              // Replace with proper format for sending to API and any additonal needed function calls.
              var postdata = $.buildQueryString({namespace: namespace});

              $.httpPost("/api/v/1/auth/set_namespace", postdata, function(res) {
                console.log("Sent namespace change request: " + namespace);
              })
            }
          })(namespace));

          list.appendChild(namespaceElem);
          ZBase.hideLoader();
          modal.show();
        });
      });
    });
  };

  var createNewDocument = function() {
    var doc_type = this.getValue();
    this.setValue([]);
    $.createNewDocument(doc_type);
  };

  var searchAutocomplete = function(e) {
    var term = e.detail.value;
    var search_widget = this;

    searchDocuments(term, function(r) {
      var documents = JSON.parse(r.response).documents;
      var items = [];

      for (var i = 0; i < documents.length; i++) {
        if (i > 10) {
          break;
        }

        items.push({
          query: documents[i].name,
          data_value: documents[i].name});
      }

      search_widget.autocomplete(term, items);
    });
  };

  var searchSubmit = function(e) {
    $("input", this).blur();
    $.navigateTo("/a/search?q=" + e.detail.value);
  };

  var searchDocuments = function(term, callback) {
    $.httpGet("/api/v1/documents?search=" + term, function(r) {
      if (r.status == 200) {
        callback(r);
      }
    });
  };

  return {
    render: render,
    update: update
  };

})();
<commit_msg>header: set input value if input elem<commit_after>var HeaderWidget = (function() {

  var render = function() {
    var conf = $.getConfig();
    var tpl = $.getTemplate("widgets/zbase-header", "zbase_header_tpl");

    $(".userid_info", tpl).innerHTML = conf.current_user.userid;
    $(".namespace_info", tpl).innerHTML = conf.current_user.namespace;

    $(".change_namespace", tpl).addEventListener("click", showSelectNamespacePopup);
    $.onClick($(".dropdown", tpl), toggleDropdown);
    $("z-search", tpl).addEventListener("z-search-autocomplete", searchAutocomplete);
    $("z-search", tpl).addEventListener("z-search-submit", searchSubmit);
    $("z-dropdown.new_query", tpl).addEventListener("change", createNewDocument);

    var elem = $("#zbase_header");
    $.replaceContent(elem, tpl);
    elem.classList.remove("hidden");

    document.addEventListener("click", function(event) {
      if ((function getParentWithClass(el, className) {
        while ((el = el.parentElement) && !el.classList.contains(className));
        return el;
      })(event.target, "dropdown")) return;

      $(".dropdown", elem).classList.remove("open");
    });

    $.handleLinks(elem);
  };

  var update = function(path) {
    var elem = $("#zbase_header");
    var input = $("z-search input", elem);

    if (!input) {
      return;
    }

    if (path.indexOf("/a/search") > -1) {
      var qparam = UrlUtil.getParamValue(path, "q");
      if (qparam != null) {
        input.value = qparam;
        return;
      }
    }

    input.value = "";
    /*
    var items = elem.querySelectorAll(".nav");
    var prev_active_item = $(".nav.active", elem);
    var active_item;

    if (prev_active_item) {
      prev_active_item.classList.remove("active");
    }

    for (var i = 0; i < items.length; i++) {
      if (path.indexOf(items[i].getAttribute("href")) == 0) {
        active_item = items[i];
      }
    }

    if (active_item) {
      active_item.classList.add("active");
    }*/
  };

  var toggleDropdown = function() {
    this.classList.toggle("open");
  };

  var showSelectNamespacePopup = function() {
    ZBase.showLoader();
    ZBase.loadModules(["widgets/z-modal"], function() {
      var tpl = $.getTemplate(
          "widgets/zbase-header",
          "zbase_header_namespace_prompt_tpl");
      var modal = $("z-modal", tpl);
      document.body.appendChild(modal);

      modal.addEventListener("z-modal-close", function() {
        document.body.removeChild(modal);
      });

      var list = modal.querySelector(".namespace_list");
      list.innerHTML = "";

      $.httpGet("/api/v1/auth/available_namespaces", function(res) {
        // Replace with parsing of actual response.
        res = ["namespace1", "namespace2", "namespace3"];

        res.forEach(function(namespace) {
          var namespaceElem = document.createElement("li");
          namespaceElem.setAttribute("data-namespace", namespace);
          namespaceElem.innerHTML = namespace;
          namespaceElem.addEventListener("click", (function(namespace) {
            return function() {
              // Replace with proper format for sending to API and any additonal needed function calls.
              var postdata = $.buildQueryString({namespace: namespace});

              $.httpPost("/api/v/1/auth/set_namespace", postdata, function(res) {
                console.log("Sent namespace change request: " + namespace);
              })
            }
          })(namespace));

          list.appendChild(namespaceElem);
          ZBase.hideLoader();
          modal.show();
        });
      });
    });
  };

  var createNewDocument = function() {
    var doc_type = this.getValue();
    this.setValue([]);
    $.createNewDocument(doc_type);
  };

  var searchAutocomplete = function(e) {
    var term = e.detail.value;
    var search_widget = this;

    searchDocuments(term, function(r) {
      var documents = JSON.parse(r.response).documents;
      var items = [];

      for (var i = 0; i < documents.length; i++) {
        if (i > 10) {
          break;
        }

        items.push({
          query: documents[i].name,
          data_value: documents[i].name});
      }

      search_widget.autocomplete(term, items);
    });
  };

  var searchSubmit = function(e) {
    $("input", this).blur();
    $.navigateTo("/a/search?q=" + e.detail.value);
  };

  var searchDocuments = function(term, callback) {
    $.httpGet("/api/v1/documents?search=" + term, function(r) {
      if (r.status == 200) {
        callback(r);
      }
    });
  };

  return {
    render: render,
    update: update
  };

})();
<|endoftext|>


<commit_before>'use strict'

const {Shm} = require('wayland-server-bindings-runtime')

const WlSurfaceRequests = require('./protocol/wayland/WlSurfaceRequests')
const WlCallback = require('./protocol/wayland/WlCallback')
const Encoder = require('./Encoder')

module.exports = class ShimSurface extends WlSurfaceRequests {
  /**
   * @param grSurfaceProxy
   * @param grSurfaceResource
   * @return {module.ShimSurface}
   */
  static create (grSurfaceProxy, grSurfaceResource) {
    const rtcBufferFactory = grSurfaceProxy.connection._rtcBufferFactory
    return new ShimSurface(grSurfaceProxy, rtcBufferFactory, grSurfaceResource)
  }

  /**
   * @private
   * @param grSurfaceProxy
   * @param rtcBufferFactory
   */
  constructor (grSurfaceProxy, rtcBufferFactory) {
    super()
    this.proxy = grSurfaceProxy
    this.rtcBufferFactory = rtcBufferFactory

    this.pendingBuffer = null
    this.buffer = null
    this.synSerial = 0
    this.ackSerial = 0
    this._encoder = Encoder.create()

    // use a single buffer to communicate with the browser. Contents of the buffer will be copied when send.
    this.localRtcDcBuffer = this.rtcBufferFactory.createLocalRtcDcBuffer()
    this.localRtcDcBuffer.ack = (serial) => {
      if (serial > this.ackSerial) {
        this.ackSerial = serial
      } // else we received an outdated ack serial, ignore it.
    }
    this.localRtcDcBuffer.latency = (serial, frameDuration) => {
      this._frameDuration = frameDuration
    }

    this.pendingBufferDestroyListener = () => {
      this.pendingBuffer = null
    }
    this.bufferDestroyListener = () => {
      this.buffer = null
    }

    this._timeOffset = Date.now()
    this._frameDuration = 0
    this._commitDuration = 0
  }

  destroy (resource) {
    this.proxy.destroy()
    resource.destroy()
    this.localRtcDcBuffer.destroy()
    this.localRtcDcBuffer = null
  }

  attach (resource, buffer, x, y) {
    // TODO listen for buffer destruction & signal buffer proxy & remove local pending buffer
    if (this.pendingBuffer) {
      this.pendingBuffer.removeDestroyListener(this.pendingBufferDestroyListener)
    }
    this.pendingBuffer = buffer
    if (this.pendingBuffer) {
      this.pendingBuffer.addDestroyListener(this.pendingBufferDestroyListener)
      this.proxy.attach(this.localRtcDcBuffer.grBufferProxy, x, y)
    } else {
      this.proxy.attach(null, x, y)
    }
  }

  damage (resource, x, y, width, height) {
    this.proxy.damage(x, y, width, height)
  }

  // This implements a smart algorithm that can fire the frame callback before the browser compositor does as to compensate
  // for network latency and encoding/decoding delays.
  frame (resource, callback) {
    const callbackResource = WlCallback.create(resource.client, 4, callback, {}, null)

    let timeoutId = -1
    if (this._frameDuration) {
      timeoutId = setTimeout(() => {
        const time = Date.now() - this._timeOffset
        callbackResource.done(time)
        timeoutId = 0
      }, this._frameDuration + this._commitDuration)
      callbackResource.onDestroy().then(() => {
        clearTimeout(timeoutId)
      })
    }

    const callbackProxy = this.proxy.frame()
    // done will be called when the browser is done rendering the frame
    callbackProxy.listener.done = (browserTimestamp) => {
      if (timeoutId) {
        // timeout hasn't fired yet, so fire it now since we are sure that the browser is done rendering.
        if (timeoutId !== -1) {
          clearTimeout(timeoutId)
        }
        const time = Date.now() - this._timeOffset
        callbackResource.done(time)
        timeoutId = 0
      }
    }
  }

  setOpaqueRegion (resource, region) {
    const regionProxy = region === null ? null : region.implementation.proxy
    this.proxy.setOpaqueRegion(regionProxy)
  }

  setInputRegion (resource, region) {
    const regionProxy = region === null ? null : region.implementation.proxy
    this.proxy.setInputRegion(regionProxy)
  }

  _encodeBuffer (buffer, synSerial) {
    const shm = Shm.get(buffer)
    if (shm === null) {
      // FIXME protocol error & disconnect client
      throw new Error('Unsupported buffer type.')
    }

    const bufferWidth = shm.getWidth()
    const bufferHeight = shm.getHeight()
    const pixelBuffer = shm.getData().reinterpret(bufferWidth * bufferHeight * 4)
    const format = shm.getFormat()

    return this._encoder.encodeBuffer(pixelBuffer, format, bufferWidth, bufferHeight, synSerial)
  }

  _frameToBuffer (frame) {
    const header = Buffer.allocUnsafe(13)
    const frameBuffer = Buffer.concat([header, frame.opaque, frame.alpha], header.length + frame.opaque.length + frame.alpha.length)

    frameBuffer.writeUInt32BE(header.length + frame.opaque.length, 0, true) // alpha offset
    frameBuffer.writeUInt16BE(frame.width, 4, true) // buffer width
    frameBuffer.writeUInt16BE(frame.height, 6, true) // buffer height
    frameBuffer.writeUInt32BE(frame.synSerial, 8, true) // frame serial
    frameBuffer.writeUInt8(frame.type, 12, true) // frame type

    return frameBuffer
  }

  _toBufferChunks (buffer, serial) {
    // certain webrtc implementations don't like it when data is > 16kb, so have have to split our buffer in chunks
    // TODO we could also set our chunk size to MTU (~1280 bytes) so they fit into a single UDP packet, on the receiving
    // end we could reconstruct these chunks and construct an incomplete NAL for partial decoding in case a chunk is missing.
    // ...patches welcome!
    const chunkSize = 16 * (1024 - 12) // 1012 because we reserve another 12 for the chunk header 1012+12=1024
    let nroChunks = 1
    if (buffer.length > chunkSize) {
      nroChunks = Math.ceil(buffer.length / chunkSize)
    }

    const chunks = []
    let chunkIdx = nroChunks
    while (chunkIdx > 0) {
      chunkIdx--
      const chunkHeader = Buffer.allocUnsafe(12)
      chunkHeader.writeUInt32BE(serial, 0, true)
      chunkHeader.writeUInt32BE(nroChunks, 4, true)
      chunkHeader.writeUInt32BE(chunkIdx, 8, true)
      const chunkStart = chunkIdx * chunkSize
      const chunkEnd = chunkStart + chunkSize
      const bufferChunk = Buffer.concat([chunkHeader, buffer.slice(chunkStart, chunkEnd)])
      chunks.push(bufferChunk)
    }
    return chunks
  }

  async sendFrame (frame) {
    if (this.localRtcDcBuffer === null) {
      return
    }

    // if the ack times out & no newer serial is expected, we can retry sending the buffer contents
    // TODO cancel timeout of we received the corresponding ack
    // setTimeout(async () => {
    //   // If the syn serial at the time the timer was created is greater than the latest received ack serial and no newer serial is expected,
    //   // then we have not received an ack that matches or is newer than the syn we're checking. We resend the frame.
    //   if (frame.synSerial > this.ackSerial && frame.synSerial === this.synSerial) {
    //     await this.sendFrame(frame)
    //   }
    //   // TODO dynamically adjust to expected roundtrip time which could be calculated by measuring the latency
    //   // between a syn & ack
    // }, 500)

    const dataChannel = await this.localRtcDcBuffer.localRtcBlobTransfer.open()
    const frameBuffer = this._frameToBuffer(frame)
    const bufferChunks = this._toBufferChunks(frameBuffer, frame.synSerial)
    bufferChunks.forEach((chunk) => {
      dataChannel.send(chunk.buffer.slice(chunk.byteOffset, chunk.byteOffset + chunk.byteLength))
    })
  }

  async commit (resource) {
    const commitStart = Date.now()
    if (this.buffer) {
      this.buffer.release()
      this.buffer.removeDestroyListener(this.bufferDestroyListener)
    }

    if (this.pendingBuffer) {
      this.pendingBuffer.removeDestroyListener(this.pendingBufferDestroyListener)
    }
    this.buffer = this.pendingBuffer
    this.pendingBuffer = null

    if (this.buffer && this.localRtcDcBuffer) {
      this.buffer.addDestroyListener(this.bufferDestroyListener)

      this.synSerial++
      const synSerial = this.synSerial
      this.localRtcDcBuffer.rtcDcBufferProxy.syn(synSerial)
      this.proxy.commit()
      const frame = await this._encodeBuffer(this.buffer, synSerial)
      await this.sendFrame(frame)
      this._commitDuration = Date.now() - commitStart
    }
  }

  setBufferTransform (resource, transform) {
    this.proxy.setBufferTransform(transform)
  }

  setBufferScale (resource, scale) {
    this.proxy.setBufferScale(scale)
  }

  damageBuffer (resource, x, y, width, height) {
    this.proxy.damageBuffer(x, y, width, height)
  }
}
<commit_msg>calculate frame callback delay based on server+browser commit total processing time<commit_after>'use strict'

const {Shm} = require('wayland-server-bindings-runtime')

const WlSurfaceRequests = require('./protocol/wayland/WlSurfaceRequests')
const WlCallback = require('./protocol/wayland/WlCallback')
const Encoder = require('./Encoder')

module.exports = class ShimSurface extends WlSurfaceRequests {
  /**
   * @param grSurfaceProxy
   * @param grSurfaceResource
   * @return {module.ShimSurface}
   */
  static create (grSurfaceProxy, grSurfaceResource) {
    const rtcBufferFactory = grSurfaceProxy.connection._rtcBufferFactory
    return new ShimSurface(grSurfaceProxy, rtcBufferFactory, grSurfaceResource)
  }

  /**
   * @private
   * @param grSurfaceProxy
   * @param rtcBufferFactory
   */
  constructor (grSurfaceProxy, rtcBufferFactory) {
    super()
    this.proxy = grSurfaceProxy
    this.rtcBufferFactory = rtcBufferFactory

    this.pendingBuffer = null
    this.buffer = null
    this.synSerial = 0
    this.ackSerial = 0
    this._encoder = Encoder.create()

    // use a single buffer to communicate with the browser. Contents of the buffer will be copied when send.
    this.localRtcDcBuffer = this.rtcBufferFactory.createLocalRtcDcBuffer()
    this.localRtcDcBuffer.ack = (serial) => {
      if (serial > this.ackSerial) {
        this.ackSerial = serial
      } // else we received an outdated ack serial, ignore it.
    }
    this.localRtcDcBuffer.latency = (serial, frameDuration) => {
      this._frameDuration = frameDuration
    }

    this.pendingBufferDestroyListener = () => {
      this.pendingBuffer = null
    }
    this.bufferDestroyListener = () => {
      this.buffer = null
    }

    this._frameDuration = 0
    this._commitDuration = 0
  }

  destroy (resource) {
    this.proxy.destroy()
    resource.destroy()
    this.localRtcDcBuffer.destroy()
    this.localRtcDcBuffer = null
  }

  attach (resource, buffer, x, y) {
    // TODO listen for buffer destruction & signal buffer proxy & remove local pending buffer
    if (this.pendingBuffer) {
      this.pendingBuffer.removeDestroyListener(this.pendingBufferDestroyListener)
    }
    this.pendingBuffer = buffer
    if (this.pendingBuffer) {
      this.pendingBuffer.addDestroyListener(this.pendingBufferDestroyListener)
      this.proxy.attach(this.localRtcDcBuffer.grBufferProxy, x, y)
    } else {
      this.proxy.attach(null, x, y)
    }
  }

  damage (resource, x, y, width, height) {
    this.proxy.damage(x, y, width, height)
  }

  frame (resource, callback) {
    this._callbackResource = WlCallback.create(resource.client, 4, callback, {}, null)
    this._callbackProxy = this.proxy.frame()
  }

  setOpaqueRegion (resource, region) {
    const regionProxy = region === null ? null : region.implementation.proxy
    this.proxy.setOpaqueRegion(regionProxy)
  }

  setInputRegion (resource, region) {
    const regionProxy = region === null ? null : region.implementation.proxy
    this.proxy.setInputRegion(regionProxy)
  }

  _encodeBuffer (buffer, synSerial) {
    const shm = Shm.get(buffer)
    if (shm === null) {
      // FIXME protocol error & disconnect client
      throw new Error('Unsupported buffer type.')
    }

    const bufferWidth = shm.getWidth()
    const bufferHeight = shm.getHeight()
    const pixelBuffer = shm.getData().reinterpret(bufferWidth * bufferHeight * 4)
    const format = shm.getFormat()

    return this._encoder.encodeBuffer(pixelBuffer, format, bufferWidth, bufferHeight, synSerial)
  }

  _frameToBuffer (frame) {
    const header = Buffer.allocUnsafe(13)
    const frameBuffer = Buffer.concat([header, frame.opaque, frame.alpha], header.length + frame.opaque.length + frame.alpha.length)

    frameBuffer.writeUInt32BE(header.length + frame.opaque.length, 0, true) // alpha offset
    frameBuffer.writeUInt16BE(frame.width, 4, true) // buffer width
    frameBuffer.writeUInt16BE(frame.height, 6, true) // buffer height
    frameBuffer.writeUInt32BE(frame.synSerial, 8, true) // frame serial
    frameBuffer.writeUInt8(frame.type, 12, true) // frame type

    return frameBuffer
  }

  _toBufferChunks (buffer, serial) {
    // certain webrtc implementations don't like it when data is > 16kb, so have have to split our buffer in chunks
    // TODO we could also set our chunk size to MTU (~1280 bytes) so they fit into a single UDP packet, on the receiving
    // end we could reconstruct these chunks and construct an incomplete NAL for partial decoding in case a chunk is missing.
    // ...patches welcome!
    const chunkSize = 16 * (1024 - 12) // 1012 because we reserve another 12 for the chunk header 1012+12=1024
    let nroChunks = 1
    if (buffer.length > chunkSize) {
      nroChunks = Math.ceil(buffer.length / chunkSize)
    }

    const chunks = []
    let chunkIdx = nroChunks
    while (chunkIdx > 0) {
      chunkIdx--
      const chunkHeader = Buffer.allocUnsafe(12)
      chunkHeader.writeUInt32BE(serial, 0, true)
      chunkHeader.writeUInt32BE(nroChunks, 4, true)
      chunkHeader.writeUInt32BE(chunkIdx, 8, true)
      const chunkStart = chunkIdx * chunkSize
      const chunkEnd = chunkStart + chunkSize
      const bufferChunk = Buffer.concat([chunkHeader, buffer.slice(chunkStart, chunkEnd)])
      chunks.push(bufferChunk)
    }
    return chunks
  }

  async sendFrame (frame) {
    if (this.localRtcDcBuffer === null) {
      return
    }

    // if the ack times out & no newer serial is expected, we can retry sending the buffer contents
    // TODO cancel timeout of we received the corresponding ack
    // setTimeout(async () => {
    //   // If the syn serial at the time the timer was created is greater than the latest received ack serial and no newer serial is expected,
    //   // then we have not received an ack that matches or is newer than the syn we're checking. We resend the frame.
    //   if (frame.synSerial > this.ackSerial && frame.synSerial === this.synSerial) {
    //     await this.sendFrame(frame)
    //   }
    //   // TODO dynamically adjust to expected roundtrip time which could be calculated by measuring the latency
    //   // between a syn & ack
    // }, 500)

    const dataChannel = await this.localRtcDcBuffer.localRtcBlobTransfer.open()
    const frameBuffer = this._frameToBuffer(frame)
    const bufferChunks = this._toBufferChunks(frameBuffer, frame.synSerial)
    bufferChunks.forEach((chunk) => {
      dataChannel.send(chunk.buffer.slice(chunk.byteOffset, chunk.byteOffset + chunk.byteLength))
    })
  }

  async commit (resource) {
    const commitStart = Date.now()

    const callbackResource = this._callbackResource
    const callbackProxy = this._callbackProxy
    const wlDisplay = resource.client.display

    if (this.buffer) {
      this.buffer.release()
      this.buffer.removeDestroyListener(this.bufferDestroyListener)
    }

    if (this.pendingBuffer) {
      this.pendingBuffer.removeDestroyListener(this.pendingBufferDestroyListener)
    }
    this.buffer = this.pendingBuffer
    this.pendingBuffer = null

    if (this.buffer && this.localRtcDcBuffer) {
      this.buffer.addDestroyListener(this.bufferDestroyListener)

      this.synSerial++
      const synSerial = this.synSerial
      this.localRtcDcBuffer.rtcDcBufferProxy.syn(synSerial)
      this.proxy.commit()
      const frame = await this._encodeBuffer(this.buffer, synSerial)
      await this.sendFrame(frame)
      this._commitDuration = Date.now() - commitStart
    }

    let timeoutId = -1
    const frameFunc = () => {
      callbackResource.done(Date.now() & 0x7fffffff)
      wlDisplay.flushClients()
      timeoutId = 0
    }

    // This implements a smart algorithm that can fire the frame callback before the browser compositor does as to compensate
    // for network latency and encoding/decoding delays.
    if (this._frameDuration && callbackResource) {
      if (this._frameDuration > this._commitDuration) {
        timeoutId = setTimeout(frameFunc, (this._frameDuration - this._commitDuration))
        callbackResource.onDestroy().then(() => {
          clearTimeout(timeoutId)
          timeoutId = 0
        })
      } else {
        frameFunc()
      }
    }

    // done will be called when the browser is done rendering the frame
    if (callbackProxy) {
      callbackProxy.listener.done = (browserTimestamp) => {
        if (timeoutId) {
          // timeout hasn't fired yet, so fire it now since we are sure that the browser is done rendering.
          if (timeoutId !== -1) {
            clearTimeout(timeoutId)
          }
          frameFunc()
        }
      }
      this._callbackProxy = null
    }
  }

  setBufferTransform (resource, transform) {
    this.proxy.setBufferTransform(transform)
  }

  setBufferScale (resource, scale) {
    this.proxy.setBufferScale(scale)
  }

  damageBuffer (resource, x, y, width, height) {
    this.proxy.damageBuffer(x, y, width, height)
  }
}
<|endoftext|>


<commit_before>var Server = require('./server');
var Friend = require('./friend');
var Movie = require('./movie');
var ko = require('knockout');
var $ = require('jquery');

function AppViewModel() {
   // PRIVATE
   //-------------
   var API_URL = 'localhost';
   var LEFT = 37;
   var RIGHT = 39;

   var ACCESS_TOKEN = $('#access-token').text();
   var self = this;
   var server = new Server(API_URL);

   var disableSwipe = false;

   var movies = [];

   var onShowDetail = function() {
     self.showDetails(true);
   };

   var maybeGetMoreMovies = function() {
       if (movies.length < 6) {
           server.getNextTrailers(function(movie) {
               // Update current movie and shift in the new movie
               self.onNewMovies(movie);
           });
       }
   };

   var nextMovie = function() {
     self.firstMovie(!self.firstMovie());
     movies.shift();
     maybeGetMoreMovies();
     if (self.firstMovie()) {
       self.nextMovie(movies[1]);
     } else {
       self.currentMovie(movies[1]);
     }
     console.log(self.currentMovie());
     console.log(self.nextMovie());
     console.log(movies);
   };

   var nextCard = function() {
     disableSwipe = true;
     console.log('next card');
     $('.film-roll').animate({'top' : '0'}, 1000, function() {
       console.log('New card down: done');

       nextMovie();

       $('.film-roll').css({'top' : '-100%'});
       var $last = $('.frame').last();
       var $first = $('.frame').first();
       $first.before($last);
       disableSwipe = false;
     });
   };

   var flipCard = function() {
     self.showDetails(!self.showDetails());
   };

   // PUBLIC
   //-------------
   self.currentMovie = ko.observable(null);
   self.nextMovie = ko.observable(null);
   self.firstMovie = ko.observable(true);
   self.showDetails = ko.observable(false);
   self.makeEventName = ko.observable("");

   self.onLikeMovie = function() {
       flipCard();
//       server.likeMovie(self.currentMovie(), function(success) {
//         flipCard();
//       });
   };

   self.onNewMovies = function(movie) {
     // Push in the new movie and update the current pointer
     movies = movies.concat(movie);

     // Fill in friend fields for each movie
     for(var i = 0; i < movie.length; i++) {
         var currentMovie = movie[i];
         (function(m) {
           server.getFriendsWhoLiked(m, function(friends) {
             m.setFriends(friends);
           });
         })(currentMovie);
     }
   };

   self.onRight = function() {
     if (!disableSwipe) {
       // First "Yes" flip
       if (!self.showDetails()) {
         self.onLikeMovie();
       } else { // Next card
         self.onLeft();
       }
     }
   };

   self.onLeft = function() {
     console.log('LEFT');
     if (!disableSwipe) {
       nextCard();
     }
   };

   // INIT
   //-------------

   $(document).keydown(function (e) {
     if(e.which == LEFT) {
       self.onLeft();
     } else if(e.which == RIGHT) {
       self.onRight();
     }
     return true;
   });

   server.getNextTrailers(function(movies) {
     // Load the movie into the queue
     self.onNewMovies(movies);
     nextMovie();
   });
}

module.exports = AppViewModel;<commit_msg>fixed<commit_after>var Server = require('./server');
var Friend = require('./friend');
var Movie = require('./movie');
var ko = require('knockout');
var $ = require('jquery');

function AppViewModel() {
   // PRIVATE
   //-------------
   var API_URL = 'localhost';
   var LEFT = 37;
   var RIGHT = 39;

   var ACCESS_TOKEN = $('#access-token').text();
   var self = this;
   var server = new Server(API_URL);

   var disableSwipe = false;

   var movies = [];

   var onShowDetail = function() {
     self.showDetails(true);
   };

   var maybeGetMoreMovies = function() {
       if (movies.length < 6) {
           server.getNextTrailers(function(movie) {
               // Update current movie and shift in the new movie
               self.onNewMovies(movie);
           });
       }
   };

   var nextMovie = function() {
     self.firstMovie(!self.firstMovie());
     movies.shift();
     maybeGetMoreMovies();
     if (self.firstMovie()) {
       self.nextMovie(movies[1]);
     } else {
       self.currentMovie(movies[1]);
     }
     console.log(self.currentMovie());
     console.log(self.nextMovie());
     console.log(movies);
   };

   var nextCard = function() {
     disableSwipe = true;
     console.log('next card');
     $('.film-roll').animate({'top' : '0'}, 1000, function() {
       console.log('New card down: done');

       nextMovie();

       $('.film-roll').css({'top' : '-100%'});
       var $last = $('.frame').last();
       var $first = $('.frame').first();
       $first.before($last);
       disableSwipe = false;
     });
   };

   var flipCard = function() {
     self.showDetails(!self.showDetails());
   };

   // PUBLIC
   //-------------
   self.currentMovie = ko.observable(null);
   self.nextMovie = ko.observable(null);
   self.firstMovie = ko.observable(true);
   self.showDetails = ko.observable(false);
   self.makeEventName = ko.observable("");

   self.onLikeMovie = function() {
       flipCard();
//       server.likeMovie(self.currentMovie(), function(success) {
//         flipCard();
//       });
   };

   self.onNewMovies = function(movie) {
     // Push in the new movie and update the current pointer
     movies = movies.concat(movie);

     // Fill in friend fields for each movie
     for(var i = 0; i < movie.length; i++) {
         var currentMovie = movie[i];
         (function(m) {
           server.getFriendsWhoLiked(m, function(friends) {
             m.setFriends(friends);
           });
         })(currentMovie);
     }
   };

   self.onRight = function() {
     if (!disableSwipe) {
       // First "Yes" flip
       if (!self.showDetails()) {
         self.onLikeMovie();
       } else { // Next card
         self.onLeft();
       }
     }
   };

   self.onLeft = function() {
     console.log('LEFT');
     if (!disableSwipe) {
       nextCard();
     }
   };

   // INIT
   //-------------

   $(document).keydown(function (e) {
     if(e.which == LEFT) {
       self.onLeft();
     } else if(e.which == RIGHT) {
       self.onRight();
     }
     return true;
   });

   server.getNextTrailers(function(movies) {
     // Load the movie into the queue
     self.onNewMovies(movies);
     self.currentMovie(movies[0]);
     self.nextMovie(movies[1]);
   });
}

module.exports = AppViewModel;<|endoftext|>


<commit_before>var Server = require('./server');
var Friend = require('./friend');
var Movie = require('./movie');
var ko = require('knockout');
var $ = require('jquery');

function AppViewModel() {
   // PRIVATE
   //-------------
   var API_URL = 'localhost';
   var LEFT = 37;
   var RIGHT = 39;

   var ACCESS_TOKEN = $('#access-token').text();
   var self = this;
   var server = new Server(API_URL);

   var disableSwipe = false;

   var movies = [];

   var onShowDetail = function() {
     self.showDetails(true);
   };

   var maybeGetMoreMovies = function() {
       if (movies.length < 6) {
           server.getNextTrailers(function(movie) {
               // Update current movie and shift in the new movie
               self.onNewMovies(movie);
               // Update current movie and shift in the new movie
               self.onNewMovie(movie);
           });
       }
   };

   var nextMovie = function() {
     self.firstMovie(!self.firstMovie());
     movies.shift();
     maybeGetMoreMovies();
     if (self.firstMovie()) {
       self.currentMovie(movies[0]);
       self.nextMovie(movies[1]);
     } else {
       self.currentMovie(movies[1]);
       self.nextMovie(movies[0]);
     }
   };

   var nextCard = function() {
     disableSwipe = true;
     console.log('next card');
     $('.film-roll').animate({'top' : '0'}, 1000, function() {
       console.log('New card down: done');

       nextMovie();

       $('.film-roll').css({'top' : '-100%'});
       $('.frame').last().prepend('.film-roll');
       disableSwipe = false;
     });
   };

   var flipCard = function() {
     self.showDetails(!self.showDetails());
   };

   // PUBLIC
   //-------------
   self.currentMovie = ko.observable(null);
   self.nextMovie = ko.observable(null);
   self.firstMovie = ko.observable(true);
   self.showDetails = ko.observable(false);
   self.makeEventName = ko.observable("");

   self.onLikeMovie = function() {
       flipCard();
//     server.likeMovie(self.currentMovie(), function(success) {
//        flipCard();
//     });
   };

   self.onNewMovies = function(movie) {
     // Push in the new movie and update the current pointer
     movies = movies.concat(movie);

     // Fill in friend fields for each movie
     for(var i = 0; i < movie.length; i++) {
//         server.getFriendsWhoLiked(movie[i], function(friends) {
//            movie[i].setFriends(friends);
//         });
     }
   };

   self.onRight = function() {
     if (!disableSwipe) {
       // First "Yes" flip
       if (!self.showDetails()) {
         self.onLikeMovie();
       } else { // Next card
         self.onLeft();
       }
     }
   };

   self.onLeft = function() {
     console.log('LEFT');
     if (!disableSwipe) {
       nextCard();
     }
   };

   // INIT
   //-------------

   $(document).keydown(function (e) {
     if(e.which == LEFT) {
       self.onLeft();
     } else if(e.which == RIGHT) {
       self.onRight();
     }
     return true;
   });

   server.getNextTrailers(function(movies) {
     // Load the movie into the queue
     self.onNewMovies(movies);
   });
}

module.exports = AppViewModel;<commit_msg>fixed<commit_after>var Server = require('./server');
var Friend = require('./friend');
var Movie = require('./movie');
var ko = require('knockout');
var $ = require('jquery');

function AppViewModel() {
   // PRIVATE
   //-------------
   var API_URL = 'localhost';
   var LEFT = 37;
   var RIGHT = 39;

   var ACCESS_TOKEN = $('#access-token').text();
   var self = this;
   var server = new Server(API_URL);

   var disableSwipe = false;

   var movies = [];

   var onShowDetail = function() {
     self.showDetails(true);
   };

   var maybeGetMoreMovies = function() {
       if (movies.length < 6) {
           server.getNextTrailers(function(movie) {
               // Update current movie and shift in the new movie
               self.onNewMovies(movie);
               // Update current movie and shift in the new movie
               self.onNewMovie(movie);
           });
       }
   };

   var nextMovie = function() {
     self.firstMovie(!self.firstMovie());
     movies.shift();
     maybeGetMoreMovies();
     if (self.firstMovie()) {
       self.currentMovie(movies[0]);
       self.nextMovie(movies[1]);
     } else {
       self.currentMovie(movies[1]);
       self.nextMovie(movies[0]);
     }
   };

   var nextCard = function() {
     disableSwipe = true;
     console.log('next card');
     $('.film-roll').animate({'top' : '0'}, 1000, function() {
       console.log('New card down: done');

       nextMovie();

       $('.film-roll').css({'top' : '-100%'});
       $('.frame').last().before($('.frame').first());
       disableSwipe = false;
     });
   };

   var flipCard = function() {
     self.showDetails(!self.showDetails());
   };

   // PUBLIC
   //-------------
   self.currentMovie = ko.observable(null);
   self.nextMovie = ko.observable(null);
   self.firstMovie = ko.observable(true);
   self.showDetails = ko.observable(false);
   self.makeEventName = ko.observable("");

   self.onLikeMovie = function() {
       flipCard();
//     server.likeMovie(self.currentMovie(), function(success) {
//        flipCard();
//     });
   };

   self.onNewMovies = function(movie) {
     // Push in the new movie and update the current pointer
     movies = movies.concat(movie);

     // Fill in friend fields for each movie
     for(var i = 0; i < movie.length; i++) {
//         server.getFriendsWhoLiked(movie[i], function(friends) {
//            movie[i].setFriends(friends);
//         });
     }
   };

   self.onRight = function() {
     if (!disableSwipe) {
       // First "Yes" flip
       if (!self.showDetails()) {
         self.onLikeMovie();
       } else { // Next card
         self.onLeft();
       }
     }
   };

   self.onLeft = function() {
     console.log('LEFT');
     if (!disableSwipe) {
       nextCard();
     }
   };

   // INIT
   //-------------

   $(document).keydown(function (e) {
     if(e.which == LEFT) {
       self.onLeft();
     } else if(e.which == RIGHT) {
       self.onRight();
     }
     return true;
   });

   server.getNextTrailers(function(movies) {
     // Load the movie into the queue
     self.onNewMovies(movies);
   });
}

module.exports = AppViewModel;<|endoftext|>


<commit_before>define(function(require) {

function Block(type) {
	this.type = type;
}
Block.prototype.mineable = function () {
	return Block.isMineable(this.type);
};
Block.prototype.invisible = function () {
	return Block.isInvisible(this.type);
};
Block.prototype.solid = function () {
	return Block.isSolid(this.type);
};

//Block Types
Block.NIL   = 0x0; //Putting this here so its clear it's reserved
Block.AIR   = 0x1;
Block.DIRT  = 0x2;
Block.STONE = 0x3;
Block.SPAWN = 0x4;

//See "Block encoding.txt"

//Block properties
Block.MINEABLE	= 0x80000000;

//Subtypes
// Invisible blocks are ignored by the renderer, and have no physical
// manifestation in the world.
Block.INVISIBLE = 0x1;
// Solid blocks are treated as solid by physics simulations, and will
// prevent entities from occupying the same space as them.
Block.SOLID = 0x2;

Block.PROPERTIES = [
	/** NIL    */ 0,
	/** AIR    */ Block.INVISIBLE,
	/** DIRT   */ Block.SOLID | Block.MINEABLE,
	/** STONE  */ Block.SOLID | Block.MINEABLE,
	/** SPAWN  */ Block.SOLID,
];

Block.ATLAS_SIZE = 128;
Block.TILE_SIZE = 16;
Block.UV_UNIT = Block.TILE_SIZE / Block.ATLAS_SIZE;

Block.ATLAS = [
	[0, 7], // Dirt / Grass bottom
	[1, 7], // Grass side
	[2, 7], // Grass top
	[3, 7], // Stone
	[4, 7], // Spawn
];

/**
 * Faces:
 * 0 - (+x) Left
 * 1 - (-x) Right
 * 2 - (+y) Top
 * 3 - (-y) Bottom
 * 4 - (+z) Front
 * 5 - (-z) Back
 */
Block.getTileOffset = function (blockType, face) {
	if (blockType === Block.DIRT) {
		if (face === 2) {
			return Block.ATLAS[2];
		} else if (face === 3) {
			return Block.ATLAS[0];
		} else {
			return Block.ATLAS[1];
		}
	} else if (blockType === Block.STONE) {
		return Block.ATLAS[3];
	} else if (blockType === Block.SPAWN) {
		return Block.ATLAS[4];
	} else {
		throw "I don't know how to render that... TYPE: " + blockType + " FACE: " + face;
	}
};

Block.isMineable = function (block) {
	return (Block.PROPERTIES[block] & Block.MINEABLE) !== 0;
};

Block.isInvisible = function (block) {
	return Block.inSubtype(block, Block.INVISIBLE);
};

Block.isSolid = function (block) {
	return Block.inSubtype(block, Block.SOLID);
};

Block.inSubtype = function (block, subtype) {
	return (Block.PROPERTIES[block]&subtype) === subtype;
};

return Block;
});
<commit_msg>Add a comment.<commit_after>define(function(require) {

function Block(type) {
	this.type = type;
}
Block.prototype.mineable = function () {
	return Block.isMineable(this.type);
};
Block.prototype.invisible = function () {
	return Block.isInvisible(this.type);
};
Block.prototype.solid = function () {
	return Block.isSolid(this.type);
};

//Block Types
Block.NIL   = 0x0; //Putting this here so its clear it's reserved
Block.AIR   = 0x1;
Block.DIRT  = 0x2;
Block.STONE = 0x3;
Block.SPAWN = 0x4;

//See "Block encoding.txt"

//Block properties
Block.MINEABLE	= 0x80000000;

//Subtypes
// Invisible blocks are ignored by the renderer, and have no physical
// manifestation in the world.
Block.INVISIBLE = 0x1;
// Solid blocks are treated as solid by physics simulations, and will
// prevent entities from occupying the same space as them.
Block.SOLID = 0x2;

Block.PROPERTIES = [
	/** NIL    */ 0,
	/** AIR    */ Block.INVISIBLE,
	/** DIRT   */ Block.SOLID | Block.MINEABLE,
	/** STONE  */ Block.SOLID | Block.MINEABLE,
	/** SPAWN  */ Block.SOLID,
];

Block.ATLAS_SIZE = 128;
Block.TILE_SIZE = 16;
Block.UV_UNIT = Block.TILE_SIZE / Block.ATLAS_SIZE;

// UV indexed from bottom left (cartesian coordinates).
Block.ATLAS = [
	[0, 7], // Dirt / Grass bottom
	[1, 7], // Grass side
	[2, 7], // Grass top
	[3, 7], // Stone
	[4, 7], // Spawn
];

/**
 * Faces:
 * 0 - (+x) Left
 * 1 - (-x) Right
 * 2 - (+y) Top
 * 3 - (-y) Bottom
 * 4 - (+z) Front
 * 5 - (-z) Back
 */
Block.getTileOffset = function (blockType, face) {
	if (blockType === Block.DIRT) {
		if (face === 2) {
			return Block.ATLAS[2];
		} else if (face === 3) {
			return Block.ATLAS[0];
		} else {
			return Block.ATLAS[1];
		}
	} else if (blockType === Block.STONE) {
		return Block.ATLAS[3];
	} else if (blockType === Block.SPAWN) {
		return Block.ATLAS[4];
	} else {
		throw "I don't know how to render that... TYPE: " + blockType + " FACE: " + face;
	}
};

Block.isMineable = function (block) {
	return (Block.PROPERTIES[block] & Block.MINEABLE) !== 0;
};

Block.isInvisible = function (block) {
	return Block.inSubtype(block, Block.INVISIBLE);
};

Block.isSolid = function (block) {
	return Block.inSubtype(block, Block.SOLID);
};

Block.inSubtype = function (block, subtype) {
	return (Block.PROPERTIES[block]&subtype) === subtype;
};

return Block;
});
<|endoftext|>


<commit_before>"use strict";
import React from 'react';
import { History } from 'react-router';
var LocalStorageMixin = require('react-localstorage');
import moment from 'moment';
moment().format();

var Organization = exports.Organization = React.createClass({
  displayName: 'Organization',
  mixins: [ History, LocalStorageMixin ],

  handleClick: function(project){
    console.log('inside of project handleClick');
    console.log('inside of handleClick project is', project);
    // console.log('inside of handleClick index is', index);
    localStorage.setItem('currProjObj', project._id);
    console.log('Project._id is ', project._id);
    this.props.navigateToProjectPage();
  },

  getInitialState: function(){
    return {
      org: null,
      following: false
    };
  },

  componentDidMount: function() {
    $.ajax({
        url:'/organization_get/' + localStorage.currentOrganization,
        method: "GET",
        success: function (data) {
          this.setState({
            org: data.results
          });

          //Initialize Materialize Components
          $('.materialboxed').materialbox();
          $('.tooltipped').tooltip({delay: 50});
          $('.scrollspy').scrollSpy();

        }.bind(this),
        error: function (xhr, status, err) {
          console.error(xhr, status, err.toString());
        }.bind(this)
      });
  },

  componentWillMount: function() {
    console.log('CWM fires: ', this.props.currentOrganization);
  },

  followOrg: function(e) {
    e.preventDefault();
    var org = this.state.org._id || this.props.currentOrganization._id;
    // feeder.emit('follow', localStorage.token, org);
    $.ajax({
      method: 'POST',
      url: '/organization/follow/' + org,
      success: function(response) {
        this.setState({ following: true });
      }.bind(this),
      error: function(xhr, status) {
        console.log("Error:", xhr, status);
      }.bind(this)
    });
  },

  render: function () {
    console.log('Token: ', localStorage.token);
    console.log('Org: ', this.state.org);
    if(this.state.org){
      var today = new Date();

      var aofs = this.state.org.areas_of_focus.map(function (aof, index) {
        return (

{aof}

        );
      }.bind(this));

      var currentProjects = this.state.org.projects.filter(function (project) {
        return moment(project.end_date).diff(today) > 0;
      }).map(function (project, index) {
        return (

{project.title}

{project.info}

Start Date:

{moment(project.start_date).format('MMMM D, YYYY')}

End Date:

{moment(project.end_date).format('MMMM D, YYYY')}

        );
      }.bind(this));

      var pastProjects = this.state.org.projects.filter(function (project) {
        return moment(project.end_date).diff(today) < 0;
      }).map(function (project, index) {
        return (

{project.title}

{project.info}

Start Date:

{moment(project.start_date).format('MMMM D, YYYY')}

End Date:

{moment(project.end_date).format('MMMM D, YYYY')}

        );
      }.bind(this));

      return (

          {/*Header*/}

              {this.state.org.name}

            {this.state.org.address ?

                room

{this.state.org.address}

 : ""
            }

            {/*Follow Button*/}

              {
                !localStorage.token || this.state.org.followers.indexOf(localStorage.token) === -1
                  ? group_add
                  : Following
              }

                {/*Image 1*/}

                  {/**/}

                {/*Org Description*/}

                  description

 Description

{this.state.org.about}

                {/*Additional Info*/}

Additional info here about what the Org Cares about. Boom and there goes the dynamite

                {/*Image 2*/}

                {/*Areas of Focus*/}

                  location_searching

 Areas of focus:

                  {aofs}

                {/*Current Project*/}

                  assignment_late

Our Current Projects:

                    {currentProjects.length > 0 ? currentProjects :
No projects to display
}

                {/*Past Projects*/}
                {pastProjects.length > 0 ?
                  (

                    assignment_turned_in

Our Past Projects:

                      {pastProjects}

) : ""}

                {/*Endorsements*/}

                  verified_user

Endorsements:

Various Endorsements

            {/*ScrollSpy*/}

              <ScrollSpyListItems
                address={this.state.org.address}
                hasPastProjects={pastProjects.length > 0}
                hasCurrentProjects={currentProjects.length > 0}
              />

      );
    } else {
      return (

nothing to display

      );
    }
  }
});

var ScrollSpyListItems = React.createClass({
  render: function () {
    return(

            {this.props.address ?

                  Location

 : ""
            }

                Description

                Areas of Focus

            {
              this.props.hasCurrentProjects ? (

                    Current Projects

              ) : (
               ""
              )
            }
            {
              this.props.hasPastProjects ? (

                    Past Projects

              ) : (
                ""
              )
            }

                Endorsements

    );
  }
});
<commit_msg>bugfix/orgPage<commit_after>"use strict";
import React from 'react';
import { History } from 'react-router';
var LocalStorageMixin = require('react-localstorage');
import moment from 'moment';
moment().format();

var Organization = exports.Organization = React.createClass({
  displayName: 'Organization',
  mixins: [ History, LocalStorageMixin ],

  handleClick: function(project){
    console.log('inside of project handleClick');
    console.log('inside of handleClick project is', project);
    // console.log('inside of handleClick index is', index);
    localStorage.setItem('currProjObj', project._id);
    console.log('Project._id is ', project._id);
    this.props.navigateToProjectPage();
  },

  getInitialState: function(){
    return {
      org: null,
      following: false
    };
  },

  componentDidMount: function() {
    $.ajax({
        url:'/organization_get/' + localStorage.currentOrganization,
        method: "GET",
        success: function (data) {
          this.setState({
            org: data.results
          });

          //Initialize Materialize Components
          $('.materialboxed').materialbox();
          $('.tooltipped').tooltip({delay: 50});
          $('.scrollspy').scrollSpy();

        }.bind(this),
        error: function (xhr, status, err) {
          console.error(xhr, status, err.toString());
        }.bind(this)
      });
  },

  componentWillMount: function() {
    console.log('CWM fires: ', this.props.currentOrganization);
  },

  followOrg: function(e) {
    e.preventDefault();
    var org = this.state.org._id || this.props.currentOrganization._id;
    // feeder.emit('follow', localStorage.token, org);
    $.ajax({
      method: 'POST',
      url: '/organization/follow/' + org,
      success: function(response) {
        this.setState({ following: true });
      }.bind(this),
      error: function(xhr, status) {
        console.log("Error:", xhr, status);
      }.bind(this)
    });
  },

  render: function () {
    console.log('Token: ', localStorage.token);
    console.log('Org: ', this.state.org);
    if(this.state.org){
      var today = new Date();

      var aofs = this.state.org.areas_of_focus.map(function (aof, index) {
        return (

{aof}

        );
      }.bind(this));

      var currentProjects = this.state.org.projects.filter(function (project) {
        return moment(project.end_date).diff(today) > 0;
      }).map(function (project, index) {
        return (

{project.title}

{project.info}

Start Date:

{moment(project.start_date).format('MMMM D, YYYY')}

End Date:

{moment(project.end_date).format('MMMM D, YYYY')}

        );
      }.bind(this));

      var pastProjects = this.state.org.projects.filter(function (project) {
        return moment(project.end_date).diff(today) < 0;
      }).map(function (project, index) {
        return (

{project.title}

{project.info}

Start Date:

{moment(project.start_date).format('MMMM D, YYYY')}

End Date:

{moment(project.end_date).format('MMMM D, YYYY')}

        );
      }.bind(this));

      return (

          {/*Header*/}

              {this.state.org.name}

            {this.state.org.address ?

                room

{this.state.org.address}

 : ""
            }

            {/*Follow Button*/}

              {
                !localStorage.token || this.state.org.followers.indexOf(localStorage.token) === -1
                  ? group_add
                  : Following
              }

                {/*Image 1*/}

                  {/**/}

                {/*Org Description*/}

                  description

 Description

{this.state.org.about}

                {/*Additional Info*/}

Additional info here about what the Org Cares about. Boom and there goes the dynamite

                {/*Image 2*/}

                {/*Areas of Focus*/}

                  location_searching

 Areas of focus:

                  {aofs}

                {/*Current Project*/}

                  assignment_late

Our Current Projects:

                    {currentProjects.length > 0 ? currentProjects :
No projects to display
}

                {/*Past Projects*/}
                {pastProjects.length > 0 ?
                  (

                    assignment_turned_in

Our Past Projects:

                      {pastProjects}

) : ""}

                {/*Endorsements*/}

                  verified_user

Endorsements:

Various Endorsements

            {/*ScrollSpy*/}

              <ScrollSpyListItems
                address={this.state.org.address}
                hasPastProjects={pastProjects.length > 0}
                hasCurrentProjects={currentProjects.length > 0}
              />

      );
    } else {
      return (

nothing to display

      );
    }
  }
});

var ScrollSpyListItems = React.createClass({
  render: function () {
    return(

            {this.props.address ?

                  Location

 : ""
            }

                Description

                Areas of Focus

            {
              this.props.hasCurrentProjects ? (

                    Current Projects

              ) : (
               ""
              )
            }
            {
              this.props.hasPastProjects ? (

                    Past Projects

              ) : (
                ""
              )
            }

                Endorsements

    );
  }
});
<|endoftext|>


<commit_before>/**
 * @file This file currently works on mock data, just to make sure that the
 * chart works.
 */
// @ts-check
// eslint-disable-next-line max-len
/** @typedef {import('./analysis/gdpr.js').CollatedGDPRRecords} CollatedGDPRRecords */

import {sleep} from './util.js';
import {getStreamingData, collateStreamingData} from './analysis/gdpr.js';

const {c3, zip} = window;

zip.workerScriptsPath = '/js/zip/';

/**
 * Populates `chart` with historical track data derived from `collatedRecords`.
 *
 * @param {CollatedGDPRRecords} collatedRecords Information about the amount of
 * time each track has been listened to on each day.
 * @param {c3.ChartAPI} chart The chart to populate.
 */
async function populateChart(collatedRecords, chart) {
  const ROLLING_WINDOW_SIZE = 28;

  // calculate song rankings based on 28-day rolling sums
  const rankingHistory = new Map();
  const rankingDates = [];
  const rollingSums = new Map();

  for (let i = 0; i < collatedRecords.intervals.length; i++) {
    rankingDates.push(collatedRecords.intervals[i].start);

    const entering = collatedRecords.intervals[i].totals;
    const exiting = i >= ROLLING_WINDOW_SIZE ?
      collatedRecords.intervals[i - ROLLING_WINDOW_SIZE].totals :
      null;

    for (const [artist, tracks] of entering) {
      for (const [track, added] of tracks) {
        const key = `${track} - ${artist}`;
        const current = rollingSums.get(key) || 0;
        rollingSums.set(key, current + added);
      }
    }

    if (exiting) {
      for (const [artist, tracks] of exiting) {
        for (const [track, removed] of tracks) {
          const key = `${track} - ${artist}`;
          const current = rollingSums.get(key) || 0;
          rollingSums.set(key, current - removed);
        }
      }
    }

    // number of songs that can be on the chart at a time
    const CHART_SIZE = 15;

    // turn into array of entries
    [...rollingSums]
        // sort by play time in the last 28 days
        .sort((entryA, entryB) => {
          if (entryA[1] > entryB[1]) return -1;
          if (entryA[1] < entryB[1]) return 1;
          return 0;
        })
        // select top 15
        .slice(0, CHART_SIZE)
        // add indexes to track history
        .forEach((entry, index) => {
          const [key] = entry;

          let trackHistory = rankingHistory.get(key);

          if (!trackHistory) {
            trackHistory = [];
            rankingHistory.set(key, trackHistory);
          }

          while (trackHistory.length  [id, ...history]);

  // load data in segments to avoid hanging the browser
  for (let i = 0; i < chartData.length; i++) {
    const chartDataSegment = chartData.slice(i, i + 15);
    await new Promise((resolve) => chart.load({
      columns: [
        ['date', ...rankingDates],
        ...chartDataSegment,
      ],
      done: resolve,
    }));

    // yield control to browser so it doesn't hang
    await sleep(400);
  }
}

const dateFormat = new Intl.DateTimeFormat('en', {
  day: 'numeric',
  month: 'short',
  year: 'numeric',
});

const chart = c3.generate({
  bindto: '#chart',
  size: {
    height: 700,
  },
  data: {
    x: 'date',
    columns: [],
    onmouseover: (d) => chart.focus(d.id),
    onmouseout: () => chart.focus(),
  },
  axis: {
    x: {
      type: 'timeseries',
      tick: {
        format: '%d/%m/%Y',
        outer: false,
        culling: {
          max: 4,
        },
      },
    },
    y: {
      show: false,
      inverted: true,
    },
  },
  tooltip: {
    grouped: false,
    contents: (d) =>
      `
        #${d[0].value + 1}
        TODO
        ${d[0].id}
        unknown artist
        ${dateFormat.format(d[0].x)}
      `,
  },
  legend: {
    show: false,
  },
  zoom: {
    enabled: true,
  },
});

const btnUpload =
  /** @type {HTMLButtonElement} */
  (document.getElementById('btn-data-upload'));

btnUpload.addEventListener('click', async () => {
  const inputUpload =
      /** @type {HTMLInputElement} */
      (document.getElementById('input-data-upload'));

  inputUpload.click();

  await new Promise(
      (resolve) => inputUpload.addEventListener(
          'change',
          resolve,
          {once: true},
      ),
  );

  if (!inputUpload.files) return;

  const fileUpload = inputUpload.files.item(0);
  if (!fileUpload) return;

  const records = await getStreamingData(fileUpload);

  const collatedRecords = collateStreamingData(records);

  populateChart(collatedRecords, chart);
});
<commit_msg>Change sleep time<commit_after>/**
 * @file This file currently works on mock data, just to make sure that the
 * chart works.
 */
// @ts-check
// eslint-disable-next-line max-len
/** @typedef {import('./analysis/gdpr.js').CollatedGDPRRecords} CollatedGDPRRecords */

import {sleep} from './util.js';
import {getStreamingData, collateStreamingData} from './analysis/gdpr.js';

const {c3, zip} = window;

zip.workerScriptsPath = '/js/zip/';

/**
 * Populates `chart` with historical track data derived from `collatedRecords`.
 *
 * @param {CollatedGDPRRecords} collatedRecords Information about the amount of
 * time each track has been listened to on each day.
 * @param {c3.ChartAPI} chart The chart to populate.
 */
async function populateChart(collatedRecords, chart) {
  const ROLLING_WINDOW_SIZE = 28;

  // calculate song rankings based on 28-day rolling sums
  const rankingHistory = new Map();
  const rankingDates = [];
  const rollingSums = new Map();

  for (let i = 0; i < collatedRecords.intervals.length; i++) {
    rankingDates.push(collatedRecords.intervals[i].start);

    const entering = collatedRecords.intervals[i].totals;
    const exiting = i >= ROLLING_WINDOW_SIZE ?
      collatedRecords.intervals[i - ROLLING_WINDOW_SIZE].totals :
      null;

    for (const [artist, tracks] of entering) {
      for (const [track, added] of tracks) {
        const key = `${track} - ${artist}`;
        const current = rollingSums.get(key) || 0;
        rollingSums.set(key, current + added);
      }
    }

    if (exiting) {
      for (const [artist, tracks] of exiting) {
        for (const [track, removed] of tracks) {
          const key = `${track} - ${artist}`;
          const current = rollingSums.get(key) || 0;
          rollingSums.set(key, current - removed);
        }
      }
    }

    // number of songs that can be on the chart at a time
    const CHART_SIZE = 15;

    // turn into array of entries
    [...rollingSums]
        // sort by play time in the last 28 days
        .sort((entryA, entryB) => {
          if (entryA[1] > entryB[1]) return -1;
          if (entryA[1] < entryB[1]) return 1;
          return 0;
        })
        // select top 15
        .slice(0, CHART_SIZE)
        // add indexes to track history
        .forEach((entry, index) => {
          const [key] = entry;

          let trackHistory = rankingHistory.get(key);

          if (!trackHistory) {
            trackHistory = [];
            rankingHistory.set(key, trackHistory);
          }

          while (trackHistory.length  [id, ...history]);

  // load data in segments to avoid hanging the browser
  for (let i = 0; i < chartData.length; i++) {
    const chartDataSegment = chartData.slice(i, i + 15);
    await new Promise((resolve) => chart.load({
      columns: [
        ['date', ...rankingDates],
        ...chartDataSegment,
      ],
      done: resolve,
    }));

    // yield control to browser so it doesn't hang
    // browser will perform any pending updates (clicks, animations, etc)
    // then return to this loop ASAP
    await sleep(0);
  }
}

const dateFormat = new Intl.DateTimeFormat('en', {
  day: 'numeric',
  month: 'short',
  year: 'numeric',
});

const chart = c3.generate({
  bindto: '#chart',
  size: {
    height: 700,
  },
  data: {
    x: 'date',
    columns: [],
    onmouseover: (d) => chart.focus(d.id),
    onmouseout: () => chart.focus(),
  },
  axis: {
    x: {
      type: 'timeseries',
      tick: {
        format: '%d/%m/%Y',
        outer: false,
        culling: {
          max: 4,
        },
      },
    },
    y: {
      show: false,
      inverted: true,
    },
  },
  tooltip: {
    grouped: false,
    contents: (d) =>
      `
        #${d[0].value + 1}
        TODO
        ${d[0].id}
        unknown artist
        ${dateFormat.format(d[0].x)}
      `,
  },
  legend: {
    show: false,
  },
  zoom: {
    enabled: true,
  },
});

const btnUpload =
  /** @type {HTMLButtonElement} */
  (document.getElementById('btn-data-upload'));

btnUpload.addEventListener('click', async () => {
  const inputUpload =
      /** @type {HTMLInputElement} */
      (document.getElementById('input-data-upload'));

  inputUpload.click();

  await new Promise(
      (resolve) => inputUpload.addEventListener(
          'change',
          resolve,
          {once: true},
      ),
  );

  if (!inputUpload.files) return;

  const fileUpload = inputUpload.files.item(0);
  if (!fileUpload) return;

  const records = await getStreamingData(fileUpload);

  const collatedRecords = collateStreamingData(records);

  populateChart(collatedRecords, chart);
});
<|endoftext|>


<commit_before>

Template.home.helpers({
    userName: function(){
        var user = Users.findOne({_id:Session.get('userId')});
        if( user ){
            return user.name;
        }
    },
    roomName: function(){
        return Session.get('roomName');
    },
    activeIfIsRoomOwner: function(){
        if( !Session.get('isRoomOwner') ){
            return 'disabled';
        }
    },
    visibleIfIsRoomOwner: function(){
        if( !Session.get('isRoomOwner') ){
            return 'display:none;';
        }
    }
});

Template.home.events({
    'keyup .user-name': function(e, tmpl){
        if( e.currentTarget.value.trim().length == 0 || e.keyCode != 8 && e.keyCode != 46 && (e.keyCode < 65 || e.keyCode > 90))
            return;
        Meteor.call('updateUserName', Session.get('roomId'), localStorage.token, e.currentTarget.value.trim(), function(error, result){
            if( !result )
                e.currentTarget.value = Users.findOne({_id:Session.get('userId')}).name;
        });
    },
    'keyup .room-name': function(e, tmpl){
        if( e.currentTarget.value.trim().length == 0 || e.keyCode != 8 && e.keyCode != 46 && (e.keyCode < 65 || e.keyCode > 90))
            return;
        Meteor.call('updateRoomName', Session.get('roomId'), localStorage.token, e.currentTarget.value.trim(), function(error, result){
            if( !result )
                e.currentTarget.value = Rooms.findOne({_id:Session.get('roomId')}).name;
        });
    },
    'click .room-destroy': function(e, tmpl){
        Meteor.call('removeRoom', Session.get('roomId'), localStorage.token, function(error, result){

        });
    }
});

Template.home.created = function(){

    Tracker.autorun(function(){

        Meteor.subscribe('messages', Session.get('roomId'));
        Meteor.subscribe('room-users', Session.get('roomId'));

        Meteor.call('isRoomOwner', Session.get('roomId'), localStorage.token, function(error, result){
            Session.set('isRoomOwner', result);
        });
        /*
         if( ){
         Users.insert({
         room: Session.get('roomId'),
         token: localStorage.token,
         name: $('.user-name').val()
         }, function(error, id) {
         Session.set('userId', id);
         });
         }
         */
        function createUser(){
            Users.insert({
                room: Session.get('roomId'),
                token: localStorage.token,
                name: $('.user-name').val()
            }, function(error, id) {
                Session.set('userId', id);
            });
        };

        if( !localStorage.token){
            localStorage.token = Random.hexString(12);
            createUser();
        }else{
            Users.update({_id: Session.get('userId')}, {
                $set:{
                    room : Session.get('roomId')
                }
            },function(){
                Meteor.call('getUser',  Session.get('roomId'), localStorage.token, function (error, result) {
                    if (error || !result) {
                        createUser();
                    } else {
                        Session.set('userId', result._id);
                    }
                });
            });
        }
        Session.set('userToken', localStorage.token);
    });

    Tracker.autorun(function(){
        var room = Rooms.findOne({_id: Session.get('roomId')});
        if( !room) {
            Session.set("roomId", null);
            Session.set('roomName', null);
        }else{
            Session.set('roomName', room.name);
        }
        window.history.replaceState(Session.get('roomName'), Session.get('roomName'), '/'+(Session.get('roomId')||''));
    });
};

<commit_msg>tatata<commit_after>

Template.home.helpers({
    userName: function(){
        var user = Users.findOne({_id:Session.get('userId')});
        if( user  && user.name == $('.user-name').val() ){
            return user.name;
        }
    },
    roomName: function(){
        return Session.get('roomName');
    },
    activeIfIsRoomOwner: function(){
        if( !Session.get('isRoomOwner') ){
            return 'disabled';
        }
    },
    visibleIfIsRoomOwner: function(){
        if( !Session.get('isRoomOwner') ){
            return 'display:none;';
        }
    }
});

Template.home.events({
    'keyup .user-name': function(e, tmpl){
        if( e.currentTarget.value.trim().length == 0 || e.keyCode != 8 && e.keyCode != 46 && (e.keyCode < 65 || e.keyCode > 90))
            return;
        Meteor.call('updateUserName', Session.get('roomId'), localStorage.token, e.currentTarget.value.trim(), function(error, result){
            if( !result )
                e.currentTarget.value = Users.findOne({_id:Session.get('userId')}).name;
        });
    },
    'keyup .room-name': function(e, tmpl){
        if( e.currentTarget.value.trim().length == 0 || e.keyCode != 8 && e.keyCode != 46 && (e.keyCode < 65 || e.keyCode > 90))
            return;
        Meteor.call('updateRoomName', Session.get('roomId'), localStorage.token, e.currentTarget.value.trim(), function(error, result){
            if( !result )
                e.currentTarget.value = Rooms.findOne({_id:Session.get('roomId')}).name;
        });
    },
    'click .room-destroy': function(e, tmpl){
        Meteor.call('removeRoom', Session.get('roomId'), localStorage.token, function(error, result){

        });
    }
});

Template.home.created = function(){

    Tracker.autorun(function(){

        Meteor.subscribe('messages', Session.get('roomId'));
        Meteor.subscribe('room-users', Session.get('roomId'));

        Meteor.call('isRoomOwner', Session.get('roomId'), localStorage.token, function(error, result){
            Session.set('isRoomOwner', result);
        });
        /*
         if( ){
         Users.insert({
         room: Session.get('roomId'),
         token: localStorage.token,
         name: $('.user-name').val()
         }, function(error, id) {
         Session.set('userId', id);
         });
         }
         */
        function createUser(){
            Users.insert({
                room: Session.get('roomId'),
                token: localStorage.token,
                name: $('.user-name').val()
            }, function(error, id) {
                Session.set('userId', id);
            });
        };

        if( !localStorage.token){
            localStorage.token = Random.hexString(12);
            createUser();
        }else{
            Users.update({_id: Session.get('userId')}, {
                $set:{
                    room : Session.get('roomId')
                }
            },function(){
                Meteor.call('getUser',  Session.get('roomId'), localStorage.token, function (error, result) {
                    if (error || !result) {
                        createUser();
                    } else {
                        Session.set('userId', result._id);
                    }
                });
            });
        }
        Session.set('userToken', localStorage.token);
    });

    Tracker.autorun(function(){
        var room = Rooms.findOne({_id: Session.get('roomId')});
        if( !room) {
            Session.set("roomId", null);
            Session.set('roomName', null);
        }else{
            Session.set('roomName', room.name);
        }
        window.history.replaceState(Session.get('roomName'), Session.get('roomName'), '/'+(Session.get('roomId')||''));
    });
};

<|endoftext|>


<commit_before>define([
    'q',
    'knockout',
    'util/galaxy',
    'api/api'
],
function (Q, ko, $galaxy, API) {
    var vm = function () {
        var self = this;

        /*
         *  ==================================================================================
         *   V I E W   V A R I A B L E S
         *  ==================================================================================
        */
        self.selectedStack = ko.observable(null);
        self.stackTitle = ko.observable();

        self.latestLogs = ko.observableArray([]);
        self.historicalLogs = ko.observableArray([]);
        self.selectedLog = ko.observable();
        self.selectedLogText = ko.observable();

        self.$galaxy = $galaxy;

        /*
         *  ==================================================================================
         *   R E G I S T R A T I O N   S E C T I O N
         *  ==================================================================================
        */
        self.id = 'stack.logs';
        self.templatePath = 'stack.logs.html';
        self.domBindingId = '#stack-logs';

        try {
            $galaxy.join(self);
        } catch (ex) {
            console.log(ex);
        }

        /*
         *  ==================================================================================
         *   E V E N T   S U B S C R I P T I O N S
         *  ==================================================================================
         */
        $galaxy.network.subscribe(self.id + '.docked', function (data) {
            self.init(data);
        });

        /*
         *  ==================================================================================
         *   V I E W   M E T H O D S
         *  ==================================================================================
         */

        self.init = function (data) {

            if (data.hasOwnProperty('stack')) {

                self.selectedLogText('Loading...');

                API.Stacks.getStack(data.stack).then(function (stack) {

                    self.selectedStack(stack);

                    self.stackTitle(stack.title);

                    API.Stacks.getLogs(stack).then(function (logs) {
                        self.logObject = logs;
                        self.historicalLogs.removeAll();
                        self.logObject.historical.forEach(function(logrecord) {
                            urlarr = logrecord.split('/');
                            self.historicalLogs.push({
                                name: urlarr[urlarr.length-1],
                                url: logrecord
                            });
                        });
                        self.latestLogs.removeAll();
                        self.latestLogs.push({
                            name: 'Launch',
                            url: self.logObject.latest.launch
                        });
                        self.latestLogs.push({
                            name: 'Provisioning',
                            url: self.logObject.latest.provisioning
                        });
                        self.latestLogs.push({
                            name: 'Provisioning Error',
                            url: self.logObject.latest['provisioning-error']
                        });
                        self.latestLogs.push({
                            name: 'Orchestration',
                            url: self.logObject.latest.orchestration
                        });
                        self.latestLogs.push({
                            name: 'Orchestration Error',
                            url: self.logObject.latest['orchestration-error']
                        });

                        // Start out with the latest launch log
                        self.goToLog(self.latestLogs()[0]);
                    }).catch(function(error) {
                        console.error(error);
                    }).done();
                });

            } else {
                $galaxy.transport('stack.list');
            }

        };

        self.goToTab = function (obj, evt) {
            var tab=evt.target.id;
            $galaxy.transport({
                location: 'stack.'+tab,
                payload: {
                    stack: self.selectedStack().id
                }
            });
        };

        self.getStatusType = function(status) {
            switch(status) {
                case 'waiting':
                    return 'info';
                case 'running':
                    return 'warning';
                case 'finished':
                    return 'success';
                default:
                    return 'default';
            }
	    };

        self.goToLog = function(obj, evt) {
            self.selectedLog(obj.name);
            self.selectedLogText("Loading...");
            API.Stacks.getLog(obj.url).then(function (log) {
                if (obj.name === self.selectedLog()) {
                    self.selectedLogText(log);
                }
            }).catch(function (error) {
                if (obj.name === self.selectedLog()) {
                    self.selectedLogText(error);
                }
            });
        };

    };
    return new vm();
});
<commit_msg>Fixed issue where UI would freeze after clicking on a log page<commit_after>define([
    'q',
    'knockout',
    'util/galaxy',
    'api/api'
],
function (Q, ko, $galaxy, API) {
    var vm = function () {
        var self = this;

        /*
         *  ==================================================================================
         *   V I E W   V A R I A B L E S
         *  ==================================================================================
        */
        self.selectedStack = ko.observable(null);
        self.stackTitle = ko.observable();

        self.latestLogs = ko.observableArray([]);
        self.historicalLogs = ko.observableArray([]);
        self.selectedLog = ko.observable();
        self.selectedLogText = ko.observable();

        self.$galaxy = $galaxy;

        /*
         *  ==================================================================================
         *   R E G I S T R A T I O N   S E C T I O N
         *  ==================================================================================
        */
        self.id = 'stack.logs';
        self.templatePath = 'stack.logs.html';
        self.domBindingId = '#stack-logs';

        try {
            $galaxy.join(self);
        } catch (ex) {
            console.log(ex);
        }

        /*
         *  ==================================================================================
         *   E V E N T   S U B S C R I P T I O N S
         *  ==================================================================================
         */
        $galaxy.network.subscribe(self.id + '.docked', function (data) {
            self.init(data);
        });

        /*
         *  ==================================================================================
         *   V I E W   M E T H O D S
         *  ==================================================================================
         */

        self.init = function (data) {

            if (data.hasOwnProperty('stack')) {

                self.selectedLogText('Loading...');

                API.Stacks.getStack(data.stack).then(function (stack) {

                    self.selectedStack(stack);

                    self.stackTitle(stack.title);

                    API.Stacks.getLogs(stack).then(function (logs) {
                        self.logObject = logs;
                        self.historicalLogs.removeAll();
                        self.logObject.historical.forEach(function(logrecord) {
                            urlarr = logrecord.split('/');
                            self.historicalLogs.push({
                                name: urlarr[urlarr.length-1],
                                url: logrecord
                            });
                        });
                        self.latestLogs.removeAll();
                        self.latestLogs.push({
                            name: 'Launch',
                            url: self.logObject.latest.launch
                        });
                        self.latestLogs.push({
                            name: 'Provisioning',
                            url: self.logObject.latest.provisioning
                        });
                        self.latestLogs.push({
                            name: 'Provisioning Error',
                            url: self.logObject.latest['provisioning-error']
                        });
                        self.latestLogs.push({
                            name: 'Orchestration',
                            url: self.logObject.latest.orchestration
                        });
                        self.latestLogs.push({
                            name: 'Orchestration Error',
                            url: self.logObject.latest['orchestration-error']
                        });

                        // Start out with the latest launch log
                        self.goToLog(self.latestLogs()[0]);
                    }).catch(function(error) {
                        console.error(error);
                    }).done();
                });

            } else {
                $galaxy.transport('stack.list');
            }

        };

        self.goToTab = function (obj, evt) {
            var tab=evt.target.id;
            // Clear out current log data so the UI isn't slow
            self.selectedLogText("Loading...");
            $galaxy.transport({
                location: 'stack.'+tab,
                payload: {
                    stack: self.selectedStack().id
                }
            });
        };

        self.getStatusType = function(status) {
            switch(status) {
                case 'waiting':
                    return 'info';
                case 'running':
                    return 'warning';
                case 'finished':
                    return 'success';
                default:
                    return 'default';
            }
	    };

        self.goToLog = function(obj, evt) {
            self.selectedLog(obj.name);
            self.selectedLogText("Loading...");
            API.Stacks.getLog(obj.url).then(function (log) {
                if (obj.name === self.selectedLog()) {
                    self.selectedLogText(log);
                }
            }).catch(function (error) {
                if (obj.name === self.selectedLog()) {
                    self.selectedLogText(error);
                }
            });
        };

    };
    return new vm();
});
<|endoftext|>