<commit_before>// ----------------------------------------------------------------------------------------
// Loading spinner
// ----------------------------------------------------------------------------------------

function startSpinning(id) {
  var counter = 0;
  function spin() {
    var el = document.getElementById(id);
    if (el == null) return;

    var offset = counter * -21;
    el.style.display = "block";
    el.style.backgroundPosition = "0px " + offset + "px";
    counter++; if (counter >= 19) counter = 0;
    setTimeout(spin, 100);
  };
  setTimeout(spin, 500);
}

// ----------------------------------------------------------------------------------------
// Logging user events
// ----------------------------------------------------------------------------------------

function guid(){
  var d = new Date().getTime();
  if (window.performance && typeof window.performance.now === "function") d += performance.now();
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = (d + Math.random()*16)%16 | 0;
      d = Math.floor(d/16);
      return (c=='x' ? r : (r&0x3|0x8)).toString(16);
  });
}

var ssid = guid();
var logStarted = false;
var pendingEvents = [];
var logTimer = -1;

function writeLog() {
  logTimer = -1;
  if (pendingEvents.length > 0)
    $.ajax({ type: 'POST', url: "http://thegamma-logs.azurewebsites.net/log/olympics",
      data:pendingEvents.join("\n"), dataType: "text", success:function(r) { } });
  pendingEvents = [];
}

function logEvent(category, evt, article, data) {
  if (!logStarted) return;
  var usrid = document.cookie.replace(/(?:(?:^|.*;\s*)coeffusrid\s*\=\s*([^;]*).*$)|^.*$/, "$1");
  if (usrid == "") {
    usrid = guid();
    document.cookie = "coeffusrid=" + usrid;
  }
  var logObj =
    { "user":usrid, "session":ssid,
      "time":(new Date()).toISOString(),
      "url":window.location.toString(),
      "article":article,
      "category":category, "event":evt, "data": data };

  pendingEvents.push(JSON.stringify(logObj));
  if (logTimer != 1) clearTimeout(logTimer);
  logTimer = setTimeout(writeLog, 4000);
}

// ----------------------------------------------------------------------------------------
// Sharing of snippets
// ----------------------------------------------------------------------------------------

var sharedCode = "";
var sharedCompiled = "";

function cannotShareSnippet() {
  $("#cannot-share-dialog").modal("show");
}

function shareSnippet(code, compiled) {
  sharedCode = code;
  sharedCompiled = compiled;

  document.getElementById("submit-title").value = "";
  document.getElementById("submit-author").value = "";
  document.getElementById("submit-info").value = "";
  document.getElementById("submit-twitter").value = "";
  $("#modal-share").css("display", "block");
  $("#modal-done").css("display", "none");
  $("#submit-error").css('visibility', 'hidden');

  $("#share-dialog").modal("show");
}

// Validate title, author and info values. If everything is good,
// send /share request to the server, wait & display confirmation
function saveAndShare()
{
  // Validate that all values have been set
  var title = document.getElementById("submit-title").value;
  var author = document.getElementById("submit-author").value;
  var twitter = document.getElementById("submit-twitter").value;
  var info = document.getElementById("submit-info").value;
  if (title == "" || author == "" || info == "")
  {
    $("#submit-error").css('visibility', 'visible');
    return;
  }

  // Send data using AJAX to the server
  var data = {
    "title": title, "author": author, "twitter": twitter,
    "description": info, "code": sharedCode, "compiled": sharedCompiled
  };

  $.ajax({
    url: "http://thegamma-snippets.azurewebsites.net/olympics", data: JSON.stringify(data),
    contentType: "application/json", type: "POST", dataType: "JSON"
  }).done(function (res) {
    // Display the confirmation window with links
    var link = "/shared/" + res + "/" + title.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");
    var ut = encodeURIComponent(title);
    var ul = encodeURIComponent("http://rio2016.thegamma.net" + link);
    document.getElementById("share-lnk-tw").href = "https://twitter.com/intent/tweet?url=" + ul + "&text=" + ut;
    document.getElementById("share-lnk-fb").href = "https://www.facebook.com/sharer.php?u=" + ul;
    document.getElementById("share-lnk-rd").href = "http://www.reddit.com/submit?url=" + ul + "&title=" + ut;
    document.getElementById("share-lnk-em").href = "mailto:?subject=" + ut + "&body=" + ul;
    document.getElementById("result-link").href = link;
    document.getElementById("result-link").innerText = title;
    $("#modal-share").css("display", "none");
    $("#modal-done").css("display", "block");
  });
}

// ----------------------------------------------------------------------------------------
// Displaying content & URL hacking
// ----------------------------------------------------------------------------------------

var sections = [];
var hiddenArticles = [];
var loaders = {};
var primaryArticle = "";
var currentSection = "";
var originalLocation = window.location.pathname;

function registerArticle(id, visible, primary) {
  if (primary) primaryArticle = id;
  if (!visible) hiddenArticles.push(id.replace(/\//g,"-"));
  sections.push(id.replace(/\//g,"-"));
}

function setRunner(article, f) {
  if (hiddenArticles.indexOf(article) == -1) f();
  else {
    var g = loaders[article];
    if (g == null) loaders[article] = f;
    else loaders[article] = function() { f(); g(); };
  }
}

function displayNext() {
  if (hiddenArticles.length > 0) {
    document.getElementById(hiddenArticles[0]).style.display = "block";
    logEvent("navigation", "dislay", hiddenArticles[0]);
    var f = loaders[hiddenArticles[0]];
    if (f) f();
    hiddenArticles = hiddenArticles.slice(1);
  }
}

function setCurrentSection(top) {
  var selDist = Number.MAX_SAFE_INTEGER;
  var selId = "";
  for(var i = 0; i < sections.length; i++) {
    var el = document.getElementById(sections[i]);
    if (el.offsetTop == 0) continue;
    var dist = Math.abs(top - el.offsetTop);
    if (dist < selDist) { selDist = dist; selId = sections[i]; }
  }
  var newSection = selId == primaryArticle ? originalLocation : ("/" + selId);
  if (currentSection == "") currentSection = newSection;
  if (newSection != currentSection) {
    currentSection = newSection;
    logEvent("navigation", "scroll", newSection);
    history.replaceState({}, newSection, newSection);
  }
}

window.onscroll = function() {
  if (sections.length == 0) return;

  var body = document.body, html = document.documentElement;
  var height = -window.innerHeight +
    Math.max(body.scrollHeight, body.offsetHeight,
      html.clientHeight, html.scrollHeight, html.offsetHeight);
  var top = document.body.scrollTop;

  setCurrentSection(top);
  if (height - top < 200) displayNext();
}
<commit_msg>Fix shared page scripts<commit_after>// ----------------------------------------------------------------------------------------
// Loading spinner
// ----------------------------------------------------------------------------------------

function startSpinning(id) {
  var counter = 0;
  function spin() {
    var el = document.getElementById(id);
    if (el == null) return;

    var offset = counter * -21;
    el.style.display = "block";
    el.style.backgroundPosition = "0px " + offset + "px";
    counter++; if (counter >= 19) counter = 0;
    setTimeout(spin, 100);
  };
  setTimeout(spin, 500);
}

// ----------------------------------------------------------------------------------------
// Logging user events
// ----------------------------------------------------------------------------------------

function guid(){
  var d = new Date().getTime();
  if (window.performance && typeof window.performance.now === "function") d += performance.now();
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = (d + Math.random()*16)%16 | 0;
      d = Math.floor(d/16);
      return (c=='x' ? r : (r&0x3|0x8)).toString(16);
  });
}

var ssid = guid();
var logStarted = false;
var pendingEvents = [];
var logTimer = -1;

function writeLog() {
  logTimer = -1;
  if (pendingEvents.length > 0)
    $.ajax({ type: 'POST', url: "http://thegamma-logs.azurewebsites.net/log/olympics",
      data:pendingEvents.join("\n"), dataType: "text", success:function(r) { } });
  pendingEvents = [];
}

function logEvent(category, evt, article, data) {
  if (!logStarted) return;
  var usrid = document.cookie.replace(/(?:(?:^|.*;\s*)coeffusrid\s*\=\s*([^;]*).*$)|^.*$/, "$1");
  if (usrid == "") {
    usrid = guid();
    document.cookie = "coeffusrid=" + usrid;
  }
  var logObj =
    { "user":usrid, "session":ssid,
      "time":(new Date()).toISOString(),
      "url":window.location.toString(),
      "article":article,
      "category":category, "event":evt, "data": data };

  pendingEvents.push(JSON.stringify(logObj));
  if (logTimer != 1) clearTimeout(logTimer);
  logTimer = setTimeout(writeLog, 4000);
}

// ----------------------------------------------------------------------------------------
// Sharing of snippets
// ----------------------------------------------------------------------------------------

var sharedCode = "";
var sharedCompiled = "";

function cannotShareSnippet() {
  $("#cannot-share-dialog").modal("show");
}

function shareSnippet(code, compiled) {
  sharedCode = code;
  sharedCompiled = compiled;

  document.getElementById("submit-title").value = "";
  document.getElementById("submit-author").value = "";
  document.getElementById("submit-info").value = "";
  document.getElementById("submit-twitter").value = "";
  $("#modal-share").css("display", "block");
  $("#modal-done").css("display", "none");
  $("#submit-error").css('visibility', 'hidden');

  $("#share-dialog").modal("show");
}

// Validate title, author and info values. If everything is good,
// send /share request to the server, wait & display confirmation
function saveAndShare()
{
  // Validate that all values have been set
  var title = document.getElementById("submit-title").value;
  var author = document.getElementById("submit-author").value;
  var twitter = document.getElementById("submit-twitter").value;
  var info = document.getElementById("submit-info").value;
  if (title == "" || author == "" || info == "")
  {
    $("#submit-error").css('visibility', 'visible');
    return;
  }

  // Send data using AJAX to the server
  var data = {
    "title": title, "author": author, "twitter": twitter,
    "description": info, "code": sharedCode, "compiled": sharedCompiled
  };

  $.ajax({
    url: "http://thegamma-snippets.azurewebsites.net/olympics", data: JSON.stringify(data),
    contentType: "application/json", type: "POST", dataType: "JSON"
  }).done(function (res) {
    // Display the confirmation window with links
    var link = "/shared/" + res + "/" + title.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");
    var ut = encodeURIComponent(title);
    var ul = encodeURIComponent("http://rio2016.thegamma.net" + link);
    document.getElementById("share-lnk-tw").href = "https://twitter.com/intent/tweet?url=" + ul + "&text=" + ut;
    document.getElementById("share-lnk-fb").href = "https://www.facebook.com/sharer.php?u=" + ul;
    document.getElementById("share-lnk-rd").href = "http://www.reddit.com/submit?url=" + ul + "&title=" + ut;
    document.getElementById("share-lnk-em").href = "mailto:?subject=" + ut + "&body=" + ul;
    document.getElementById("result-link").href = link;
    document.getElementById("result-link").innerText = title;
    $("#modal-share").css("display", "none");
    $("#modal-done").css("display", "block");
  });
}

// ----------------------------------------------------------------------------------------
// Displaying content & URL hacking
// ----------------------------------------------------------------------------------------

var sections = [];
var sectionUrls = [];
var hiddenArticles = [];
var loaders = {};
var primaryArticle = "";
var currentSection = "";
var originalLocation = window.location.pathname;

function registerArticle(id, visible, primary) {
  if (primary) primaryArticle = id;
  if (!visible) hiddenArticles.push(id.replace(/\//g,"-"));
  sectionUrls.push(id);
  sections.push(id.replace(/\//g,"-"));
}

function setRunner(article, f) {
  if (hiddenArticles.indexOf(article) == -1) f();
  else {
    var g = loaders[article];
    if (g == null) loaders[article] = f;
    else loaders[article] = function() { f(); g(); };
  }
}

function displayNext() {
  if (hiddenArticles.length > 0) {
    document.getElementById(hiddenArticles[0]).style.display = "block";
    logEvent("navigation", "dislay", hiddenArticles[0]);
    var f = loaders[hiddenArticles[0]];
    if (f) f();
    hiddenArticles = hiddenArticles.slice(1);
  }
}

function setCurrentSection(top) {
  var selDist = Number.MAX_SAFE_INTEGER;
  var selId = "";
  var selUrl = "";
  for(var i = 0; i < sections.length; i++) {
    var el = document.getElementById(sections[i]);
    if (el.offsetTop == 0) continue;
    var dist = Math.abs(top - el.offsetTop);
    if (dist < selDist) { selDist = dist; selId = sections[i]; selUrl = sectionUrls[i]; }
  }
  var newSection = selId == primaryArticle ? originalLocation : ("/" + selId);
  if (currentSection == "") currentSection = newSection;
  if (newSection != currentSection) {
    currentSection = newSection;
    logEvent("navigation", "scroll", newSection);
    history.replaceState({}, "/" + selUrl, "/" + selUrl);
  }
}

window.onscroll = function() {
  if (sections.length == 0) return;

  var body = document.body, html = document.documentElement;
  var height = -window.innerHeight +
    Math.max(body.scrollHeight, body.offsetHeight,
      html.clientHeight, html.scrollHeight, html.offsetHeight);
  var top = document.body.scrollTop;

  setCurrentSection(top);
  if (height - top < 200) displayNext();
}
<|endoftext|>


<commit_before>define(
  ['plugin/PluginBase',
  'plugin/PluginConfig',
  'fs',
  'path',
  'module',
  'util',
  '../package.json',
  './ParseDump',
  './NesC_XML_Generator'],
  function (PluginBase, PluginConfig, fs, path, module, util, pjson,
    ParseDump, NesC_XML_Generator) {
    "use strict";

    var TinyOSPopulate = function () {
      PluginBase.call(this);
    };

    TinyOSPopulate.prototype = Object.create(PluginBase.prototype);
    TinyOSPopulate.prototype.constructor = TinyOSPopulate;
    TinyOSPopulate.prototype.getName = function() {
      return "TinyOS Populator";
    };
    TinyOSPopulate.prototype.getVersion = function () {
      return pjson.version;
    };

    TinyOSPopulate.prototype.getDefaultConfig = function() {
      return new PluginConfig();
    };

    TinyOSPopulate.prototype.main = function (callback) {
      var self = this;
      self._loadNodes(self.rootNode, function(err) {
        if (err) {
          self.result.setSuccess(false);
          callback(err, self.result);
        } else {
          self._wi("Nodes are loaded");
          try {
            var pd = new ParseDump();
            var nxg = new NesC_XML_Generator('exp430');
            self._objectPath = {};
            nxg.getDirectories(function(error, directories) {
              if (error !== null) {
                self._wi("Can't get platform directories");
                self.result.setSuccess(false);
                callback(error, self.result);
              } else {
                var components_paths = nxg.getComponents(directories);
                self._created_components = {};
                x(0);
              }
              var flag = true;
              function x(index) {
                if ( flag && index >= components_paths.length ) {
                  // flag = false;
                  self._wi("Completed");
                  self.save('save populator finished', function(err) {
                    self.result.setSuccess(true);
                    callback(err, self.result);
                  });
                } else {
                  // components_paths[0] = '/home/hakan/Documents/mcr_ide/Icra2015ExptAppC.nc';
                  nxg.getXML(components_paths[index], function(error, xml) {
                    if (error !== null) {
                      self._wi("Error in generating xml: " +
                        index + components_paths[index]);
                    } else {
                      self._wi(index + " " + components_paths[index] + " prog");
                      self._app_json = pd.parse(components_paths[index], xml);
                      // fs.writeFileSync('xml.log/' + index + '.xml', xml);
                      // fs.writeFileSync('xml.log/' + index + '.js',
                      //                  util.inspect(self._app_json, {
                      //                   showHidden: true,
                      //                   depth: 5
                      //                  }));
                      // self._wij(self._app_json);
                      // self._wi(xml);
                      self._populate();
                    }
                    x(index+1);
                  });
                }

              }
            });

          } catch(error) {
            self._wi("Error in TinyOSPopulate Main");
            self._wi(error.stack);
            self.result.setSuccess(false);
            callback(error, self.result);
          }

        }
      });

    };

    TinyOSPopulate.prototype._populate = function () {
      var self = this;

      self._wi("Creating Interfaces");
      for (var key in self._app_json.interfacedefs) {
        if (self._created_components[key]) continue;
        self._createInterface(self._app_json.interfacedefs[key]);
        self._created_components[key] = true;
      }

      self._wi("Creating Components");
      for (key in self._app_json.components) {
        if (self._created_components[key]) continue;
        self._createComponent(self._app_json.components[key]);
      }

      self._wi("Creating Uses & Provides Interfaces");
      for (key in self._app_json.components) {
        if (self._created_components[key]) continue;
        self._createUPInterfaces(self._app_json.components[key]);
      }

      self._wi("Creating Wirings");
      for (key in self._app_json.components) {
        if (self._created_components[key]) continue;
        self._createWirings(self._app_json.components[key]);
        self._created_components[key] = true;
      }

    };

    TinyOSPopulate.prototype._createWirings = function(component) {
      var self = this;
      self._wi("Creating wirings for " + component.name);
      var created = {};
      for (var i = component.wiring.length - 1; i >= 0; i--) {
        var wire = component.wiring[i];
        var fc = getWiringComponent(wire.from);
        var tc = getWiringComponent(wire.to);
        var base_type = self.META.Link_Interface;
        if (fc && Array.isArray(fc)) {
          fc = fc[0];
          base_type = self.META.Equate_Interface;
        }
        if (tc && Array.isArray(tc)) {
          tc = tc[0];
          base_type = self.META.Equate_Interface;
        }
        if (fc && tc) {
          var fi = getWiringInterface(fc, wire.from.interface);
          var ti = getWiringInterface(tc, wire.to.interface);
          if (fi && ti) {
            self._wi("Creating wiring ... " +
                     component.name + " " + wire.to.interface);
            var wiring_node = self.core.createNode({
              base: base_type,
              parent: self._getObjectByPath(component.file_path),
            });
            self.core.setPointer(wiring_node, 'src', fi);
            self.core.setPointer(wiring_node, 'dst', ti);
            if (wire.from.cst) {
              self.core.setAttribute(wiring_node, 'src_params',
                                   'cst:' + wire.from.cst);
            }
            if (wire.to.cst) {
              self.core.setAttribute(wiring_node, 'dst_params',
                                   'cst:' + wire.to.cst);
            }
            self._cacheNode(wiring_node);
          }
        }
      }

      function getWiringInterface(c, c_interface) {
        var c_ids = self.core.getChildrenRelids(c);
        var interface_node = null;
        for (var i = c_ids.length - 1; i >= 0; i--) {
          var interf_child = self.core.getChild(c, c_ids[i]);
          var interface_name = self.core.getAttribute(interf_child, 'name');
          if (interface_name == c_interface) return interf_child;
        }
        return null;
      }

      function getWiringComponent(wc) {
        if (component.file_path === wc.component_base) {
          message("Wiring component is component itself");
          return [self._getObjectByPath(component.file_path), 'equate'];
        }
        if (wc.component_base in created) {
          message("Wiring component is already created");
          return created[wc.component_base];
        }
        if (self._app_json.components[get_name(wc.component_base)].generic) {
          message("Wiring component is generic type");
          // v3
          var p = wc.component_base + wc.name + '_s';
          p = p.replace('.', '', 'g');
          if (p in created) {
          } else {
            created[p] = createWiringInstance(wc.name);
          }
          return created[p];
        }
        created[wc.component_base] = self._createWiringComponent(
                                                    component.file_path, wc);
        return created[wc.component_base];

        function message(msg) {
          self._wi(msg + ": " + wc.component_base + " - " + wc.interface);
        }

        function createWiringInstance(name) {
          message("Creating wiring component instance");
          var x = self._app_json.instance_components[name];
          var wiring_component = self.core.createNode({
            base: self._getObjectByPath(x.base),
            parent: self._getObjectByPath(component.file_path)
          });
          var n = name.split('.');
          self.core.setAttribute(wiring_component, 'name', n[n.length-1]);
          self._cacheNode(wiring_component);
          return wiring_component;
        }
      }

      function get_name(c_path) {
        return path.basename(c_path, '.nc');
      }

    };

    TinyOSPopulate.prototype._createWiringComponent = function(parent_p, f) {
      var self = this;
      self._wi("Creating wiring component: " +
               f.component_base + " - " + f.interface);
      var wiring_component = self.core.createNode({
        base: self._getObjectByPath(f.component_base),
        parent: self._getObjectByPath(parent_p)
      });
      self._cacheNode(wiring_component);
      return wiring_component;
    };

    TinyOSPopulate.prototype._createUPInterfaces = function (component) {
      var self = this;
      for (var i = component.interface_types.length - 1; i >= 0; i--) {
        var curr_interface = component.interface_types[i];
        self._wi("Creating uses/provides interface: " + curr_interface.as +
          " at " + component.file_path);
        var base = self.META.Uses_Interface;
        if (curr_interface.provided === 1)
          base = self.META.Provides_Interface;
        var interface_node = self.core.createNode({
          base: base,
          parent: self._nodeCache[self._objectPath[component.file_path]],
        });
        self.core.setAttribute(interface_node, 'name', curr_interface.as);

        if (curr_interface.argument_type) {
          self.core.setAttribute(interface_node, 'type_arguments',
                               curr_interface.argument_type);
        }

        var ref_fpath = self._app_json.interfacedefs[curr_interface.name]
          .file_path;
        self.core.setPointer(interface_node, 'interface',
                             self._nodeCache[self._objectPath[ref_fpath]]);
        self._cacheNode(interface_node);
      }

    };

    TinyOSPopulate.prototype._createComponent = function (component) {
      var self = this;
      self._wi("Creating component: " + component.name);
      var parent_node = self._mkdir_p(path.dirname(component.file_path));
      var component_node = self.core.createNode({
        base: getBase(),
        parent: parent_node
      });
      self.core.setAttribute(component_node, 'name', component.name);
      self.core.setAttribute(component_node, 'safe', component.safe);
      self.core.setAttribute(component_node, 'path', component.file_path);
      self.core.setAttribute(component_node, 'source',
                             self._getSource(component.file_path));
      self._cacheNode(component_node);
      self._storeObjectPath(component, component_node);

      function getBase() {
        if (component.comp_type == 'Module') {
          return component.generic ?
            self.META.Generic_Module : self.META.Module;
        }
        return component.generic ?
          self.META.Generic_Configuration : self.META.Configuration;
      }
    };

    TinyOSPopulate.prototype._createInterface = function (curr_interface) {
      var self = this;
      self._wi("Creating interface: " + curr_interface.name);
      var parent_node = self._mkdir_p(path.dirname(curr_interface.file_path));
      var interface_node = self.core.createNode({
        base: self.META.Interface_Definition,
        parent: parent_node
      });
      self.core.setAttribute(interface_node, 'name', curr_interface.name);
      self.core.setAttribute(interface_node, 'path', curr_interface.file_path);
      self.core.setAttribute(interface_node, 'source',
                             self._getSource(curr_interface.file_path));
      self._cacheNode(interface_node);
      self._storeObjectPath(curr_interface, interface_node);
    };

    TinyOSPopulate.prototype._getObjectByPath = function(path) {
      return this._nodeCache[this._objectPath[path]];
    };

    TinyOSPopulate.prototype._storeObjectPath = function (component, node) {
      this._objectPath[component.file_path] = this.core.getPath(node);
    };

    /**
     * Make a directory in WebGME. At any directory level,
     * if the provided directory does not exist, it will be created.
     */
    TinyOSPopulate.prototype._mkdir_p = function (path) {
      var self = this;
      self._wi("Path: " + path);
      var dirs = path.split('/');
      var parent_node = self.rootNode;
      for (var i = 0; i < dirs.length; i++) {
        var dir_node = self._findNodeByName(parent_node, dirs[i]);
        if (!dir_node) {
          self._wi("Creating directory: " + dirs[i]);
          dir_node = self.core.createNode({
            base: self.META.Folder,
            parent: parent_node
          });
          self.core.setAttribute(dir_node, 'name', dirs[i]);
          self._cacheNode(dir_node);
        } else {
          self._wi("Skipping directory: " + dirs[i]);
        }
        parent_node = dir_node;
      }
      return parent_node;
    };

    TinyOSPopulate.prototype._getSource = function(path) {
      var p = require('path');
      return fs.readFileSync(p.join(process.env.TOSROOT, '/', path), {
        encoding: 'utf8'
      });
    };

    // Tamas' implementation
    TinyOSPopulate.prototype._loadNodes = function (start_node, callback) {
      var self = this;
      self._nodeCache = {};

      var load = function(node, fn) {
        self.core.loadChildren(node, function(err, children) {
          if (err) {
            fn(err);
          } else {
            var recCalls = children.length;
            var error = null;

            if(recCalls === 0){
              fn(null);
            }

            for (var i = 0; i < children.length; i++) {
              self._nodeCache[self.core.getPath(children[i])] = children[i];
              load(children[i], load_err_handler);
            }

          }

          function load_err_handler(err) {
            error = error || err;
            if(--recCalls === 0) { //callback only on last child
              fn(error);
            }
          }

        });
      };

      load(start_node, callback);
    };

    // log messages to file and console at the same time
    TinyOSPopulate.prototype._wi = function (msg) {
      var self = this;
      self.logger.warn(msg);
      self.logger.info(msg);
    };

    TinyOSPopulate.prototype._wij = function(obj) {
      var node_cache_string = util.inspect(obj, {
        showHidden: true,
        depth: 5
      });
      this._wi(node_cache_string);
    };

    TinyOSPopulate.prototype._getNodeName = function (node) {
      return this.core.getAttribute(node, 'name');
    };

    TinyOSPopulate.prototype._getNode = function (nodePath){
      //we check only our node cache
      return this._nodeCache[nodePath];
    };

    TinyOSPopulate.prototype._cacheNode = function (node) {
      this._nodeCache[this.core.getPath(node)] = node;
    };

    /**
     * Fetch the child nodes of a given node from the cache
     */
    TinyOSPopulate.prototype._getChildren = function (node) {
      var self = this;
      var children_paths = self.core.getChildrenPaths(node);
      var children = [];
      children_paths.forEach(function(child_path) {
        var child = self._getNode(child_path);
        if (child)
          children.push(child);
      });
      return children;
    };

    /**
     * Searches through the children of a given node and finds the first node
     * that has
     * the specified name. If a node is not found, null is returned.
     * If the children argument is given, it will be used instead of fetching
     * it using _getChildren. This is useful when
     * repeated calls to _findNodeByName need to be made.
     */
    TinyOSPopulate.prototype._findNodeByName = function (node, name,
      children) {
      var self = this;
      if (!children)
        children = this._getChildren(node);
      var result = null;
      for (var i = 0; i < children.length; i++) {
        var child = children[i];
        if (this._getNodeName(child) === name) {
          result = children[i];
          break;
        }
      }
      return result;
    };

    return TinyOSPopulate;
  }
);
<commit_msg>Get the platform name from config.json, default is exp430<commit_after>define(
  ['plugin/PluginBase',
  'plugin/PluginConfig',
  'fs',
  'path',
  'module',
  'util',
  '../package.json',
  '../config.json',
  './ParseDump',
  './NesC_XML_Generator'],
  function (PluginBase, PluginConfig, fs, path, module, util, pjson,
    config_json, ParseDump, NesC_XML_Generator) {
    "use strict";

    var TinyOSPopulate = function () {
      PluginBase.call(this);
    };

    TinyOSPopulate.prototype = Object.create(PluginBase.prototype);
    TinyOSPopulate.prototype.constructor = TinyOSPopulate;
    TinyOSPopulate.prototype.getName = function() {
      return "TinyOS Populator";
    };
    TinyOSPopulate.prototype.getVersion = function () {
      return pjson.version;
    };

    TinyOSPopulate.prototype.getDefaultConfig = function() {
      return new PluginConfig();
    };

    TinyOSPopulate.prototype.main = function (callback) {
      var self = this;
      self._loadNodes(self.rootNode, function(err) {
        if (err) {
          self.result.setSuccess(false);
          callback(err, self.result);
        } else {
          self._wi("Nodes are loaded");
          try {
            var pd = new ParseDump();
            var nxg = new NesC_XML_Generator(config_json.platform || 'exp430');
            self._objectPath = {};
            nxg.getDirectories(function(error, directories) {
              if (error !== null) {
                self._wi("Can't get platform directories");
                self.result.setSuccess(false);
                callback(error, self.result);
              } else {
                var components_paths = nxg.getComponents(directories);
                self._created_components = {};
                x(0);
              }
              var flag = true;
              function x(index) {
                if ( flag && index >= components_paths.length ) {
                  // flag = false;
                  self._wi("Completed");
                  self.save('save populator finished', function(err) {
                    self.result.setSuccess(true);
                    callback(err, self.result);
                  });
                } else {
                  // components_paths[0] = '/home/hakan/Documents/mcr_ide/Icra2015ExptAppC.nc';
                  nxg.getXML(components_paths[index], function(error, xml) {
                    if (error !== null) {
                      self._wi("Error in generating xml: " +
                        index + components_paths[index]);
                    } else {
                      self._wi(index + " " + components_paths[index] + " prog");
                      self._app_json = pd.parse(components_paths[index], xml);
                      // fs.writeFileSync('xml.log/' + index + '.xml', xml);
                      // fs.writeFileSync('xml.log/' + index + '.js',
                      //                  util.inspect(self._app_json, {
                      //                   showHidden: true,
                      //                   depth: 5
                      //                  }));
                      // self._wij(self._app_json);
                      // self._wi(xml);
                      self._populate();
                    }
                    x(index+1);
                  });
                }

              }
            });

          } catch(error) {
            self._wi("Error in TinyOSPopulate Main");
            self._wi(error.stack);
            self.result.setSuccess(false);
            callback(error, self.result);
          }

        }
      });

    };

    TinyOSPopulate.prototype._populate = function () {
      var self = this;

      self._wi("Creating Interfaces");
      for (var key in self._app_json.interfacedefs) {
        if (self._created_components[key]) continue;
        self._createInterface(self._app_json.interfacedefs[key]);
        self._created_components[key] = true;
      }

      self._wi("Creating Components");
      for (key in self._app_json.components) {
        if (self._created_components[key]) continue;
        self._createComponent(self._app_json.components[key]);
      }

      self._wi("Creating Uses & Provides Interfaces");
      for (key in self._app_json.components) {
        if (self._created_components[key]) continue;
        self._createUPInterfaces(self._app_json.components[key]);
      }

      self._wi("Creating Wirings");
      for (key in self._app_json.components) {
        if (self._created_components[key]) continue;
        self._createWirings(self._app_json.components[key]);
        self._created_components[key] = true;
      }

    };

    TinyOSPopulate.prototype._createWirings = function(component) {
      var self = this;
      self._wi("Creating wirings for " + component.name);
      var created = {};
      for (var i = component.wiring.length - 1; i >= 0; i--) {
        var wire = component.wiring[i];
        var fc = getWiringComponent(wire.from);
        var tc = getWiringComponent(wire.to);
        var base_type = self.META.Link_Interface;
        if (fc && Array.isArray(fc)) {
          fc = fc[0];
          base_type = self.META.Equate_Interface;
        }
        if (tc && Array.isArray(tc)) {
          tc = tc[0];
          base_type = self.META.Equate_Interface;
        }
        if (fc && tc) {
          var fi = getWiringInterface(fc, wire.from.interface);
          var ti = getWiringInterface(tc, wire.to.interface);
          if (fi && ti) {
            self._wi("Creating wiring ... " +
                     component.name + " " + wire.to.interface);
            var wiring_node = self.core.createNode({
              base: base_type,
              parent: self._getObjectByPath(component.file_path),
            });
            self.core.setPointer(wiring_node, 'src', fi);
            self.core.setPointer(wiring_node, 'dst', ti);
            if (wire.from.cst) {
              self.core.setAttribute(wiring_node, 'src_params',
                                   'cst:' + wire.from.cst);
            }
            if (wire.to.cst) {
              self.core.setAttribute(wiring_node, 'dst_params',
                                   'cst:' + wire.to.cst);
            }
            self._cacheNode(wiring_node);
          }
        }
      }

      function getWiringInterface(c, c_interface) {
        var c_ids = self.core.getChildrenRelids(c);
        var interface_node = null;
        for (var i = c_ids.length - 1; i >= 0; i--) {
          var interf_child = self.core.getChild(c, c_ids[i]);
          var interface_name = self.core.getAttribute(interf_child, 'name');
          if (interface_name == c_interface) return interf_child;
        }
        return null;
      }

      function getWiringComponent(wc) {
        if (component.file_path === wc.component_base) {
          message("Wiring component is component itself");
          return [self._getObjectByPath(component.file_path), 'equate'];
        }
        if (wc.component_base in created) {
          message("Wiring component is already created");
          return created[wc.component_base];
        }
        if (self._app_json.components[get_name(wc.component_base)].generic) {
          message("Wiring component is generic type");
          // v3
          var p = wc.component_base + wc.name + '_s';
          p = p.replace('.', '', 'g');
          if (p in created) {
          } else {
            created[p] = createWiringInstance(wc.name);
          }
          return created[p];
        }
        created[wc.component_base] = self._createWiringComponent(
                                                    component.file_path, wc);
        return created[wc.component_base];

        function message(msg) {
          self._wi(msg + ": " + wc.component_base + " - " + wc.interface);
        }

        function createWiringInstance(name) {
          message("Creating wiring component instance");
          var x = self._app_json.instance_components[name];
          var wiring_component = self.core.createNode({
            base: self._getObjectByPath(x.base),
            parent: self._getObjectByPath(component.file_path)
          });
          var n = name.split('.');
          self.core.setAttribute(wiring_component, 'name', n[n.length-1]);
          self._cacheNode(wiring_component);
          return wiring_component;
        }
      }

      function get_name(c_path) {
        return path.basename(c_path, '.nc');
      }

    };

    TinyOSPopulate.prototype._createWiringComponent = function(parent_p, f) {
      var self = this;
      self._wi("Creating wiring component: " +
               f.component_base + " - " + f.interface);
      var wiring_component = self.core.createNode({
        base: self._getObjectByPath(f.component_base),
        parent: self._getObjectByPath(parent_p)
      });
      self._cacheNode(wiring_component);
      return wiring_component;
    };

    TinyOSPopulate.prototype._createUPInterfaces = function (component) {
      var self = this;
      for (var i = component.interface_types.length - 1; i >= 0; i--) {
        var curr_interface = component.interface_types[i];
        self._wi("Creating uses/provides interface: " + curr_interface.as +
          " at " + component.file_path);
        var base = self.META.Uses_Interface;
        if (curr_interface.provided === 1)
          base = self.META.Provides_Interface;
        var interface_node = self.core.createNode({
          base: base,
          parent: self._nodeCache[self._objectPath[component.file_path]],
        });
        self.core.setAttribute(interface_node, 'name', curr_interface.as);

        if (curr_interface.argument_type) {
          self.core.setAttribute(interface_node, 'type_arguments',
                               curr_interface.argument_type);
        }

        var ref_fpath = self._app_json.interfacedefs[curr_interface.name]
          .file_path;
        self.core.setPointer(interface_node, 'interface',
                             self._nodeCache[self._objectPath[ref_fpath]]);
        self._cacheNode(interface_node);
      }

    };

    TinyOSPopulate.prototype._createComponent = function (component) {
      var self = this;
      self._wi("Creating component: " + component.name);
      var parent_node = self._mkdir_p(path.dirname(component.file_path));
      var component_node = self.core.createNode({
        base: getBase(),
        parent: parent_node
      });
      self.core.setAttribute(component_node, 'name', component.name);
      self.core.setAttribute(component_node, 'safe', component.safe);
      self.core.setAttribute(component_node, 'path', component.file_path);
      self.core.setAttribute(component_node, 'source',
                             self._getSource(component.file_path));
      self._cacheNode(component_node);
      self._storeObjectPath(component, component_node);

      function getBase() {
        if (component.comp_type == 'Module') {
          return component.generic ?
            self.META.Generic_Module : self.META.Module;
        }
        return component.generic ?
          self.META.Generic_Configuration : self.META.Configuration;
      }
    };

    TinyOSPopulate.prototype._createInterface = function (curr_interface) {
      var self = this;
      self._wi("Creating interface: " + curr_interface.name);
      var parent_node = self._mkdir_p(path.dirname(curr_interface.file_path));
      var interface_node = self.core.createNode({
        base: self.META.Interface_Definition,
        parent: parent_node
      });
      self.core.setAttribute(interface_node, 'name', curr_interface.name);
      self.core.setAttribute(interface_node, 'path', curr_interface.file_path);
      self.core.setAttribute(interface_node, 'source',
                             self._getSource(curr_interface.file_path));
      self._cacheNode(interface_node);
      self._storeObjectPath(curr_interface, interface_node);
    };

    TinyOSPopulate.prototype._getObjectByPath = function(path) {
      return this._nodeCache[this._objectPath[path]];
    };

    TinyOSPopulate.prototype._storeObjectPath = function (component, node) {
      this._objectPath[component.file_path] = this.core.getPath(node);
    };

    /**
     * Make a directory in WebGME. At any directory level,
     * if the provided directory does not exist, it will be created.
     */
    TinyOSPopulate.prototype._mkdir_p = function (path) {
      var self = this;
      self._wi("Path: " + path);
      var dirs = path.split('/');
      var parent_node = self.rootNode;
      for (var i = 0; i < dirs.length; i++) {
        var dir_node = self._findNodeByName(parent_node, dirs[i]);
        if (!dir_node) {
          self._wi("Creating directory: " + dirs[i]);
          dir_node = self.core.createNode({
            base: self.META.Folder,
            parent: parent_node
          });
          self.core.setAttribute(dir_node, 'name', dirs[i]);
          self._cacheNode(dir_node);
        } else {
          self._wi("Skipping directory: " + dirs[i]);
        }
        parent_node = dir_node;
      }
      return parent_node;
    };

    TinyOSPopulate.prototype._getSource = function(path) {
      var p = require('path');
      return fs.readFileSync(p.join(process.env.TOSROOT, '/', path), {
        encoding: 'utf8'
      });
    };

    // Tamas' implementation
    TinyOSPopulate.prototype._loadNodes = function (start_node, callback) {
      var self = this;
      self._nodeCache = {};

      var load = function(node, fn) {
        self.core.loadChildren(node, function(err, children) {
          if (err) {
            fn(err);
          } else {
            var recCalls = children.length;
            var error = null;

            if(recCalls === 0){
              fn(null);
            }

            for (var i = 0; i < children.length; i++) {
              self._nodeCache[self.core.getPath(children[i])] = children[i];
              load(children[i], load_err_handler);
            }

          }

          function load_err_handler(err) {
            error = error || err;
            if(--recCalls === 0) { //callback only on last child
              fn(error);
            }
          }

        });
      };

      load(start_node, callback);
    };

    // log messages to file and console at the same time
    TinyOSPopulate.prototype._wi = function (msg) {
      var self = this;
      self.logger.warn(msg);
      self.logger.info(msg);
    };

    TinyOSPopulate.prototype._wij = function(obj) {
      var node_cache_string = util.inspect(obj, {
        showHidden: true,
        depth: 5
      });
      this._wi(node_cache_string);
    };

    TinyOSPopulate.prototype._getNodeName = function (node) {
      return this.core.getAttribute(node, 'name');
    };

    TinyOSPopulate.prototype._getNode = function (nodePath){
      //we check only our node cache
      return this._nodeCache[nodePath];
    };

    TinyOSPopulate.prototype._cacheNode = function (node) {
      this._nodeCache[this.core.getPath(node)] = node;
    };

    /**
     * Fetch the child nodes of a given node from the cache
     */
    TinyOSPopulate.prototype._getChildren = function (node) {
      var self = this;
      var children_paths = self.core.getChildrenPaths(node);
      var children = [];
      children_paths.forEach(function(child_path) {
        var child = self._getNode(child_path);
        if (child)
          children.push(child);
      });
      return children;
    };

    /**
     * Searches through the children of a given node and finds the first node
     * that has
     * the specified name. If a node is not found, null is returned.
     * If the children argument is given, it will be used instead of fetching
     * it using _getChildren. This is useful when
     * repeated calls to _findNodeByName need to be made.
     */
    TinyOSPopulate.prototype._findNodeByName = function (node, name,
      children) {
      var self = this;
      if (!children)
        children = this._getChildren(node);
      var result = null;
      for (var i = 0; i < children.length; i++) {
        var child = children[i];
        if (this._getNodeName(child) === name) {
          result = children[i];
          break;
        }
      }
      return result;
    };

    return TinyOSPopulate;
  }
);
<|endoftext|>


<commit_before>import Cartesian3 from "../../Core/Cartesian3.js";
import Check from "../../Core/Check.js";
import ComponentDatatype from "../../Core/ComponentDatatype.js";
import defaultValue from "../../Core/defaultValue.js";
import defer from "../../Core/defer.js";
import defined from "../../Core/defined.js";
import Ellipsoid from "../../Core/Ellipsoid.js";
import IndexDatatype from "../../Core/IndexDatatype.js";
import Matrix4 from "../../Core/Matrix4.js";
import PrimitiveType from "../../Core/PrimitiveType.js";
import RuntimeError from "../../Core/RuntimeError.js";
import Transforms from "../../Core/Transforms.js";
import AttributeType from "../AttributeType.js";
import JsonMetadataTable from "../JsonMetadataTable.js";
import MetadataSchema from "../MetadataSchema.js";
import ModelComponents from "../ModelComponents.js";
import PropertyTable from "../PropertyTable.js";
import ResourceLoader from "../ResourceLoader.js";
import StructuralMetadata from "../StructuralMetadata.js";
import VertexAttributeSemantic from "../VertexAttributeSemantic.js";
import Buffer from "../../Renderer/Buffer.js";
import BufferUsage from "../../Renderer/BufferUsage.js";

/**
 * Loads a GeoJson model as part of the MAXAR_content_geojson extension with the following constraints:
 *

 *
The top level GeoJSON type must be FeatureCollection or Feature.

 *
The geometry types must be LineString, MultiLineString, MultiPolygon, or Polygon.

 *
All geometries are converted to geodesic lines.

 *
Only WGS84 geographic coordinates are supported.

 *

 *

 * Implements the {@link ResourceLoader} interface.
 *

 *
 * @alias GeoJsonLoader
 * @constructor
 * @augments ResourceLoader
 * @private
 *
 * @param {Object} options Object with the following properties:
 * @param {Object} options.geoJson The GeoJson object.
 */
export default function GeoJsonLoader(options) {
  options = defaultValue(options, defaultValue.EMPTY_OBJECT);

  //>>includeStart('debug', pragmas.debug);
  Check.typeOf.object("options.geoJson", options.geoJson);
  //>>includeEnd('debug');

  this._geoJson = options.geoJson;
  this._promise = defer();
  this._components = undefined;
}

if (defined(Object.create)) {
  GeoJsonLoader.prototype = Object.create(ResourceLoader.prototype);
  GeoJsonLoader.prototype.constructor = GeoJsonLoader;
}

Object.defineProperties(GeoJsonLoader.prototype, {
  /**
   * A promise that resolves to the resource when the resource is ready.
   *
   * @memberof GeoJsonLoader.prototype
   *
   * @type {Promise.<GeoJsonLoader>}
   * @readonly
   * @private
   */
  promise: {
    get: function () {
      return this._promise.promise;
    },
  },
  /**
   * The cache key of the resource.
   *
   * @memberof GeoJsonLoader.prototype
   *
   * @type {String}
   * @readonly
   * @private
   */
  cacheKey: {
    get: function () {
      return undefined;
    },
  },
  /**
   * The loaded components.
   *
   * @memberof GeoJsonLoader.prototype
   *
   * @type {ModelComponents.Components}
   * @readonly
   * @private
   */
  components: {
    get: function () {
      return this._components;
    },
  },
});

/**
 * Loads the resource.
 * @private
 */
GeoJsonLoader.prototype.load = function () {
  // Nothing to load
};

/**
 * Processes the resource until it becomes ready.
 *
 * @param {FrameState} frameState The frame state.
 * @private
 */
GeoJsonLoader.prototype.process = function (frameState) {
  //>>includeStart('debug', pragmas.debug);
  Check.typeOf.object("frameState", frameState);
  //>>includeEnd('debug');

  if (defined(this._components)) {
    return;
  }

  this._components = parse(this._geoJson, frameState);
  this._geoJson = undefined;
  this._promise.resolve(this);
};

function ParsedFeature() {
  this.lines = undefined;
  this.properties = undefined;
}

function ParseResult() {
  this.features = [];
}

function parsePosition(position) {
  const x = position[0];
  const y = position[1];
  const z = defaultValue(position[2], 0.0);
  return new Cartesian3(x, y, z);
}

function parseLineString(coordinates) {
  const positionsLength = coordinates.length;
  const line = new Array(positionsLength);
  for (let i = 0; i < positionsLength; i++) {
    line[i] = parsePosition(coordinates[i]);
  }
  const lines = [line];
  return lines;
}

function parseMultiLineString(coordinates) {
  const linesLength = coordinates.length;
  const lines = new Array(linesLength);
  for (let i = 0; i < linesLength; i++) {
    lines[i] = parseLineString(coordinates[i])[0];
  }
  return lines;
}

function parsePolygon(coordinates) {
  // Treat exterior polygon and interior polygons as lines
  const linesLength = coordinates.length;
  const lines = new Array(linesLength);
  for (let i = 0; i < linesLength; i++) {
    lines[i] = parseLineString(coordinates[i])[0];
  }
  return lines;
}

function parseMultiPolygon(coordinates) {
  const polygonsLength = coordinates.length;
  const lines = [];
  for (let i = 0; i < polygonsLength; i++) {
    Array.prototype.push.apply(lines, parsePolygon(coordinates[i]));
  }
  return lines;
}

const geometryTypes = {
  LineString: parseLineString,
  MultiLineString: parseMultiLineString,
  MultiPolygon: parseMultiPolygon,
  Polygon: parsePolygon,
};

function parseFeature(feature, result) {
  if (!defined(feature.geometry)) {
    return;
  }

  const geometryType = feature.geometry.type;
  const geometryFunction = geometryTypes[geometryType];
  const coordinates = feature.geometry.coordinates;

  if (!defined(geometryFunction)) {
    return;
  }

  if (!defined(coordinates)) {
    return;
  }

  const parsedFeature = new ParsedFeature();
  parsedFeature.lines = geometryFunction(coordinates);
  parsedFeature.properties = feature.properties;

  result.features.push(parsedFeature);
}

function parseFeatureCollection(featureCollection, result) {
  const features = featureCollection.features;
  const featuresLength = features.length;
  for (let i = 0; i < featuresLength; i++) {
    parseFeature(features[i], result);
  }
}

const geoJsonObjectTypes = {
  FeatureCollection: parseFeatureCollection,
  Feature: parseFeature,
};

const scratchCartesian = new Cartesian3();

function parse(geoJson, frameState) {
  const result = new ParseResult();

  const parseFunction = geoJsonObjectTypes[geoJson.type];
  if (defined(parseFunction)) {
    parseFunction(geoJson, result);
  }

  const featureCount = result.features.length;

  if (featureCount === 0) {
    throw new RuntimeError("GeoJSON must have at least one feature");
  }

  const properties = {};

  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    const featureProperties = defaultValue(
      feature.properties,
      defaultValue.EMPTY_OBJECT
    );
    for (const propertyId in featureProperties) {
      if (featureProperties.hasOwnProperty(propertyId)) {
        if (!defined(properties[propertyId])) {
          properties[propertyId] = new Array(featureCount);
        }
      }
    }
  }

  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    for (const propertyId in properties) {
      if (properties.hasOwnProperty(propertyId)) {
        const value = defaultValue(feature.properties[propertyId], "");
        properties[propertyId][i] = value;
      }
    }
  }

  const jsonMetadataTable = new JsonMetadataTable({
    count: featureCount,
    properties: properties,
  });

  const propertyTable = new PropertyTable({
    id: 0,
    count: featureCount,
    jsonMetadataTable: jsonMetadataTable,
  });
  const propertyTables = [propertyTable];

  const schema = new MetadataSchema({});

  const structuralMetadata = new StructuralMetadata({
    schema: schema,
    propertyTables: propertyTables,
  });

  const cartographicMin = new Cartesian3(
    Number.POSITIVE_INFINITY,
    Number.POSITIVE_INFINITY,
    Number.POSITIVE_INFINITY
  );

  const cartographicMax = new Cartesian3(
    Number.NEGATIVE_INFINITY,
    Number.NEGATIVE_INFINITY,
    Number.NEGATIVE_INFINITY
  );

  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    const linesLength = feature.lines.length;
    for (let j = 0; j < linesLength; j++) {
      const line = feature.lines[j];
      const positionsLength = line.length;
      for (let k = 0; k < positionsLength; k++) {
        Cartesian3.minimumByComponent(
          cartographicMin,
          line[k],
          cartographicMin
        );
        Cartesian3.maximumByComponent(
          cartographicMax,
          line[k],
          cartographicMax
        );
      }
    }
  }

  const cartographicCenter = Cartesian3.midpoint(
    cartographicMin,
    cartographicMax,
    new Cartesian3()
  );
  const ecefCenter = Cartesian3.fromDegrees(
    cartographicCenter.x,
    cartographicCenter.y,
    cartographicCenter.z,
    Ellipsoid.WGS84,
    new Cartesian3()
  );
  const toGlobal = Transforms.eastNorthUpToFixedFrame(
    ecefCenter,
    Ellipsoid.WGS84,
    new Matrix4()
  );
  const toLocal = Matrix4.inverseTransformation(toGlobal, new Matrix4());

  let vertexCount = 0;
  let indexCount = 0;

  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    const linesLength = feature.lines.length;
    for (let j = 0; j < linesLength; j++) {
      const line = feature.lines[j];
      vertexCount += line.length;
      indexCount += (line.length - 1) * 2;
    }
  }

  const positionsTypedArray = new Float32Array(vertexCount * 3);
  const featureIdsTypedArray = new Float32Array(vertexCount);
  const indicesTypedArray = IndexDatatype.createTypedArray(
    vertexCount,
    indexCount
  );
  const indexDatatype = IndexDatatype.fromTypedArray(indicesTypedArray);

  const localMin = new Cartesian3(
    Number.POSITIVE_INFINITY,
    Number.POSITIVE_INFINITY,
    Number.POSITIVE_INFINITY
  );

  const localMax = new Cartesian3(
    Number.NEGATIVE_INFINITY,
    Number.NEGATIVE_INFINITY,
    Number.NEGATIVE_INFINITY
  );

  let vertexCounter = 0;
  let segmentCounter = 0;

  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    const linesLength = feature.lines.length;
    for (let j = 0; j < linesLength; j++) {
      const line = feature.lines[j];
      const positionsLength = line.length;
      for (let k = 0; k < positionsLength; k++) {
        const cartographic = line[k];
        const globalCartesian = Cartesian3.fromDegrees(
          cartographic.x,
          cartographic.y,
          cartographic.z,
          Ellipsoid.WGS84,
          scratchCartesian
        );
        const localCartesian = Matrix4.multiplyByPoint(
          toLocal,
          globalCartesian,
          scratchCartesian
        );

        Cartesian3.minimumByComponent(localMin, localCartesian, localMin);
        Cartesian3.maximumByComponent(localMax, localCartesian, localMax);

        Cartesian3.pack(localCartesian, positionsTypedArray, vertexCounter * 3);

        featureIdsTypedArray[vertexCounter] = i;

        if (k < positionsLength - 1) {
          indicesTypedArray[segmentCounter * 2] = vertexCounter;
          indicesTypedArray[segmentCounter * 2 + 1] = vertexCounter + 1;
          segmentCounter++;
        }

        vertexCounter++;
      }
    }
  }

  const positionBuffer = Buffer.createVertexBuffer({
    typedArray: positionsTypedArray,
    context: frameState.context,
    usage: BufferUsage.STATIC_DRAW,
  });
  positionBuffer.vertexArrayDestroyable = false;

  const featureIdBuffer = Buffer.createVertexBuffer({
    typedArray: featureIdsTypedArray,
    context: frameState.context,
    usage: BufferUsage.STATIC_DRAW,
  });
  featureIdBuffer.vertexArrayDestroyable = false;

  const indexBuffer = Buffer.createIndexBuffer({
    typedArray: indicesTypedArray,
    context: frameState.context,
    usage: BufferUsage.STATIC_DRAW,
    indexDatatype: indexDatatype,
  });
  indexBuffer.vertexArrayDestroyable = false;

  const positionAttribute = new ModelComponents.Attribute();
  positionAttribute.semantic = VertexAttributeSemantic.POSITION;
  positionAttribute.componentDatatype = ComponentDatatype.FLOAT;
  positionAttribute.type = AttributeType.VEC3;
  positionAttribute.count = vertexCount;
  positionAttribute.min = localMin;
  positionAttribute.max = localMax;
  positionAttribute.buffer = positionBuffer;

  const featureIdAttribute = new ModelComponents.Attribute();
  featureIdAttribute.semantic = VertexAttributeSemantic.FEATURE_ID;
  featureIdAttribute.setIndex = 0;
  featureIdAttribute.componentDatatype = ComponentDatatype.FLOAT;
  featureIdAttribute.type = AttributeType.SCALAR;
  featureIdAttribute.count = vertexCount;
  featureIdAttribute.buffer = featureIdBuffer;

  const attributes = [positionAttribute, featureIdAttribute];

  const material = new ModelComponents.Material();
  material.unlit = true;

  const indices = new ModelComponents.Indices();
  indices.indexDatatype = indexDatatype;
  indices.count = indicesTypedArray.length;
  indices.buffer = indexBuffer;

  const featureId = new ModelComponents.FeatureIdAttribute();
  featureId.featureCount = featureCount;
  featureId.propertyTableId = 0;
  featureId.setIndex = 0;
  featureId.positionalLabel = "featureId_0";

  const featureIds = [featureId];

  const primitive = new ModelComponents.Primitive();
  primitive.attributes = attributes;
  primitive.indices = indices;
  primitive.featureIds = featureIds;
  primitive.primitiveType = PrimitiveType.LINES;
  primitive.material = material;

  const primitives = [primitive];

  const node = new ModelComponents.Node();
  node.index = 0;
  node.primitives = primitives;

  const nodes = [node];

  const scene = new ModelComponents.Scene();
  scene.nodes = nodes;

  const components = new ModelComponents.Components();
  components.scene = scene;
  components.nodes = nodes;
  components.transform = toGlobal;
  components.structuralMetadata = structuralMetadata;

  return components;
}

/**
 * Unloads the resource.
 * @private
 */
GeoJsonLoader.prototype.unload = function () {
  this._components = undefined;
};
<commit_msg>Add comments<commit_after>import Cartesian3 from "../../Core/Cartesian3.js";
import Check from "../../Core/Check.js";
import ComponentDatatype from "../../Core/ComponentDatatype.js";
import defaultValue from "../../Core/defaultValue.js";
import defer from "../../Core/defer.js";
import defined from "../../Core/defined.js";
import Ellipsoid from "../../Core/Ellipsoid.js";
import IndexDatatype from "../../Core/IndexDatatype.js";
import Matrix4 from "../../Core/Matrix4.js";
import PrimitiveType from "../../Core/PrimitiveType.js";
import RuntimeError from "../../Core/RuntimeError.js";
import Transforms from "../../Core/Transforms.js";
import AttributeType from "../AttributeType.js";
import JsonMetadataTable from "../JsonMetadataTable.js";
import MetadataSchema from "../MetadataSchema.js";
import ModelComponents from "../ModelComponents.js";
import PropertyTable from "../PropertyTable.js";
import ResourceLoader from "../ResourceLoader.js";
import StructuralMetadata from "../StructuralMetadata.js";
import VertexAttributeSemantic from "../VertexAttributeSemantic.js";
import Buffer from "../../Renderer/Buffer.js";
import BufferUsage from "../../Renderer/BufferUsage.js";

/**
 * Loads a GeoJson model as part of the MAXAR_content_geojson extension with the following constraints:
 *

 *
The top level GeoJSON type must be FeatureCollection or Feature.

 *
The geometry types must be LineString, MultiLineString, MultiPolygon, or Polygon.

 *
All geometries are converted to geodesic lines.

 *
Only WGS84 geographic coordinates are supported.

 *

 *

 * Implements the {@link ResourceLoader} interface.
 *

 *
 * @alias GeoJsonLoader
 * @constructor
 * @augments ResourceLoader
 * @private
 *
 * @param {Object} options Object with the following properties:
 * @param {Object} options.geoJson The GeoJson object.
 */
export default function GeoJsonLoader(options) {
  options = defaultValue(options, defaultValue.EMPTY_OBJECT);

  //>>includeStart('debug', pragmas.debug);
  Check.typeOf.object("options.geoJson", options.geoJson);
  //>>includeEnd('debug');

  this._geoJson = options.geoJson;
  this._promise = defer();
  this._components = undefined;
}

if (defined(Object.create)) {
  GeoJsonLoader.prototype = Object.create(ResourceLoader.prototype);
  GeoJsonLoader.prototype.constructor = GeoJsonLoader;
}

Object.defineProperties(GeoJsonLoader.prototype, {
  /**
   * A promise that resolves to the resource when the resource is ready.
   *
   * @memberof GeoJsonLoader.prototype
   *
   * @type {Promise.<GeoJsonLoader>}
   * @readonly
   * @private
   */
  promise: {
    get: function () {
      return this._promise.promise;
    },
  },
  /**
   * The cache key of the resource.
   *
   * @memberof GeoJsonLoader.prototype
   *
   * @type {String}
   * @readonly
   * @private
   */
  cacheKey: {
    get: function () {
      return undefined;
    },
  },
  /**
   * The loaded components.
   *
   * @memberof GeoJsonLoader.prototype
   *
   * @type {ModelComponents.Components}
   * @readonly
   * @private
   */
  components: {
    get: function () {
      return this._components;
    },
  },
});

/**
 * Loads the resource.
 * @private
 */
GeoJsonLoader.prototype.load = function () {
  // Nothing to load
};

/**
 * Processes the resource until it becomes ready.
 *
 * @param {FrameState} frameState The frame state.
 * @private
 */
GeoJsonLoader.prototype.process = function (frameState) {
  //>>includeStart('debug', pragmas.debug);
  Check.typeOf.object("frameState", frameState);
  //>>includeEnd('debug');

  if (defined(this._components)) {
    return;
  }

  this._components = parse(this._geoJson, frameState);
  this._geoJson = undefined;
  this._promise.resolve(this);
};

function ParsedFeature() {
  this.lines = undefined;
  this.properties = undefined;
}

function ParseResult() {
  this.features = [];
}

function parsePosition(position) {
  const x = position[0];
  const y = position[1];
  const z = defaultValue(position[2], 0.0);
  return new Cartesian3(x, y, z);
}

function parseLineString(coordinates) {
  const positionsLength = coordinates.length;
  const line = new Array(positionsLength);
  for (let i = 0; i < positionsLength; i++) {
    line[i] = parsePosition(coordinates[i]);
  }
  const lines = [line];
  return lines;
}

function parseMultiLineString(coordinates) {
  const linesLength = coordinates.length;
  const lines = new Array(linesLength);
  for (let i = 0; i < linesLength; i++) {
    lines[i] = parseLineString(coordinates[i])[0];
  }
  return lines;
}

function parsePolygon(coordinates) {
  // Treat exterior polygon and interior polygons as lines
  const linesLength = coordinates.length;
  const lines = new Array(linesLength);
  for (let i = 0; i < linesLength; i++) {
    lines[i] = parseLineString(coordinates[i])[0];
  }
  return lines;
}

function parseMultiPolygon(coordinates) {
  const polygonsLength = coordinates.length;
  const lines = [];
  for (let i = 0; i < polygonsLength; i++) {
    Array.prototype.push.apply(lines, parsePolygon(coordinates[i]));
  }
  return lines;
}

const geometryTypes = {
  LineString: parseLineString,
  MultiLineString: parseMultiLineString,
  MultiPolygon: parseMultiPolygon,
  Polygon: parsePolygon,
};

function parseFeature(feature, result) {
  if (!defined(feature.geometry)) {
    return;
  }

  const geometryType = feature.geometry.type;
  const geometryFunction = geometryTypes[geometryType];
  const coordinates = feature.geometry.coordinates;

  if (!defined(geometryFunction)) {
    return;
  }

  if (!defined(coordinates)) {
    return;
  }

  const parsedFeature = new ParsedFeature();
  parsedFeature.lines = geometryFunction(coordinates);
  parsedFeature.properties = feature.properties;

  result.features.push(parsedFeature);
}

function parseFeatureCollection(featureCollection, result) {
  const features = featureCollection.features;
  const featuresLength = features.length;
  for (let i = 0; i < featuresLength; i++) {
    parseFeature(features[i], result);
  }
}

const geoJsonObjectTypes = {
  FeatureCollection: parseFeatureCollection,
  Feature: parseFeature,
};

const scratchCartesian = new Cartesian3();

function parse(geoJson, frameState) {
  const result = new ParseResult();

  // Parse the GeoJSON
  const parseFunction = geoJsonObjectTypes[geoJson.type];
  if (defined(parseFunction)) {
    parseFunction(geoJson, result);
  }

  const featureCount = result.features.length;

  if (featureCount === 0) {
    throw new RuntimeError("GeoJSON must have at least one feature");
  }

  // Allocate space for property values
  const properties = {};
  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    const featureProperties = defaultValue(
      feature.properties,
      defaultValue.EMPTY_OBJECT
    );
    for (const propertyId in featureProperties) {
      if (featureProperties.hasOwnProperty(propertyId)) {
        if (!defined(properties[propertyId])) {
          properties[propertyId] = new Array(featureCount);
        }
      }
    }
  }

  // Fill in the property values. Default to empty string for undefined values.
  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    for (const propertyId in properties) {
      if (properties.hasOwnProperty(propertyId)) {
        const value = defaultValue(feature.properties[propertyId], "");
        properties[propertyId][i] = value;
      }
    }
  }

  const jsonMetadataTable = new JsonMetadataTable({
    count: featureCount,
    properties: properties,
  });

  const propertyTable = new PropertyTable({
    id: 0,
    count: featureCount,
    jsonMetadataTable: jsonMetadataTable,
  });
  const propertyTables = [propertyTable];

  const schema = new MetadataSchema({});

  const structuralMetadata = new StructuralMetadata({
    schema: schema,
    propertyTables: propertyTables,
  });

  // Find the cartographic bounding box
  const cartographicMin = new Cartesian3(
    Number.POSITIVE_INFINITY,
    Number.POSITIVE_INFINITY,
    Number.POSITIVE_INFINITY
  );

  const cartographicMax = new Cartesian3(
    Number.NEGATIVE_INFINITY,
    Number.NEGATIVE_INFINITY,
    Number.NEGATIVE_INFINITY
  );

  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    const linesLength = feature.lines.length;
    for (let j = 0; j < linesLength; j++) {
      const line = feature.lines[j];
      const positionsLength = line.length;
      for (let k = 0; k < positionsLength; k++) {
        Cartesian3.minimumByComponent(
          cartographicMin,
          line[k],
          cartographicMin
        );
        Cartesian3.maximumByComponent(
          cartographicMax,
          line[k],
          cartographicMax
        );
      }
    }
  }

  // Compute the ENU matrix
  const cartographicCenter = Cartesian3.midpoint(
    cartographicMin,
    cartographicMax,
    new Cartesian3()
  );
  const ecefCenter = Cartesian3.fromDegrees(
    cartographicCenter.x,
    cartographicCenter.y,
    cartographicCenter.z,
    Ellipsoid.WGS84,
    new Cartesian3()
  );
  const toGlobal = Transforms.eastNorthUpToFixedFrame(
    ecefCenter,
    Ellipsoid.WGS84,
    new Matrix4()
  );
  const toLocal = Matrix4.inverseTransformation(toGlobal, new Matrix4());

  // Count the number of vertices and indices
  let vertexCount = 0;
  let indexCount = 0;

  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    const linesLength = feature.lines.length;
    for (let j = 0; j < linesLength; j++) {
      const line = feature.lines[j];
      vertexCount += line.length;
      indexCount += (line.length - 1) * 2;
    }
  }

  // Allocate typed arrays
  const positionsTypedArray = new Float32Array(vertexCount * 3);
  const featureIdsTypedArray = new Float32Array(vertexCount);
  const indicesTypedArray = IndexDatatype.createTypedArray(
    vertexCount,
    indexCount
  );
  const indexDatatype = IndexDatatype.fromTypedArray(indicesTypedArray);

  // Process the data. Convert positions to local ENU. Generate indices.
  const localMin = new Cartesian3(
    Number.POSITIVE_INFINITY,
    Number.POSITIVE_INFINITY,
    Number.POSITIVE_INFINITY
  );

  const localMax = new Cartesian3(
    Number.NEGATIVE_INFINITY,
    Number.NEGATIVE_INFINITY,
    Number.NEGATIVE_INFINITY
  );

  let vertexCounter = 0;
  let segmentCounter = 0;

  for (let i = 0; i < featureCount; i++) {
    const feature = result.features[i];
    const linesLength = feature.lines.length;
    for (let j = 0; j < linesLength; j++) {
      const line = feature.lines[j];
      const positionsLength = line.length;
      for (let k = 0; k < positionsLength; k++) {
        const cartographic = line[k];
        const globalCartesian = Cartesian3.fromDegrees(
          cartographic.x,
          cartographic.y,
          cartographic.z,
          Ellipsoid.WGS84,
          scratchCartesian
        );
        const localCartesian = Matrix4.multiplyByPoint(
          toLocal,
          globalCartesian,
          scratchCartesian
        );

        Cartesian3.minimumByComponent(localMin, localCartesian, localMin);
        Cartesian3.maximumByComponent(localMax, localCartesian, localMax);

        Cartesian3.pack(localCartesian, positionsTypedArray, vertexCounter * 3);

        featureIdsTypedArray[vertexCounter] = i;

        if (k < positionsLength - 1) {
          indicesTypedArray[segmentCounter * 2] = vertexCounter;
          indicesTypedArray[segmentCounter * 2 + 1] = vertexCounter + 1;
          segmentCounter++;
        }

        vertexCounter++;
      }
    }
  }

  // Create GPU buffers
  const positionBuffer = Buffer.createVertexBuffer({
    typedArray: positionsTypedArray,
    context: frameState.context,
    usage: BufferUsage.STATIC_DRAW,
  });
  positionBuffer.vertexArrayDestroyable = false;

  const featureIdBuffer = Buffer.createVertexBuffer({
    typedArray: featureIdsTypedArray,
    context: frameState.context,
    usage: BufferUsage.STATIC_DRAW,
  });
  featureIdBuffer.vertexArrayDestroyable = false;

  const indexBuffer = Buffer.createIndexBuffer({
    typedArray: indicesTypedArray,
    context: frameState.context,
    usage: BufferUsage.STATIC_DRAW,
    indexDatatype: indexDatatype,
  });
  indexBuffer.vertexArrayDestroyable = false;

  // Create ModelComponents
  const positionAttribute = new ModelComponents.Attribute();
  positionAttribute.semantic = VertexAttributeSemantic.POSITION;
  positionAttribute.componentDatatype = ComponentDatatype.FLOAT;
  positionAttribute.type = AttributeType.VEC3;
  positionAttribute.count = vertexCount;
  positionAttribute.min = localMin;
  positionAttribute.max = localMax;
  positionAttribute.buffer = positionBuffer;

  const featureIdAttribute = new ModelComponents.Attribute();
  featureIdAttribute.semantic = VertexAttributeSemantic.FEATURE_ID;
  featureIdAttribute.setIndex = 0;
  featureIdAttribute.componentDatatype = ComponentDatatype.FLOAT;
  featureIdAttribute.type = AttributeType.SCALAR;
  featureIdAttribute.count = vertexCount;
  featureIdAttribute.buffer = featureIdBuffer;

  const attributes = [positionAttribute, featureIdAttribute];

  const material = new ModelComponents.Material();
  material.unlit = true;

  const indices = new ModelComponents.Indices();
  indices.indexDatatype = indexDatatype;
  indices.count = indicesTypedArray.length;
  indices.buffer = indexBuffer;

  const featureId = new ModelComponents.FeatureIdAttribute();
  featureId.featureCount = featureCount;
  featureId.propertyTableId = 0;
  featureId.setIndex = 0;
  featureId.positionalLabel = "featureId_0";

  const featureIds = [featureId];

  const primitive = new ModelComponents.Primitive();
  primitive.attributes = attributes;
  primitive.indices = indices;
  primitive.featureIds = featureIds;
  primitive.primitiveType = PrimitiveType.LINES;
  primitive.material = material;

  const primitives = [primitive];

  const node = new ModelComponents.Node();
  node.index = 0;
  node.primitives = primitives;

  const nodes = [node];

  const scene = new ModelComponents.Scene();
  scene.nodes = nodes;

  const components = new ModelComponents.Components();
  components.scene = scene;
  components.nodes = nodes;
  components.transform = toGlobal;
  components.structuralMetadata = structuralMetadata;

  return components;
}

/**
 * Unloads the resource.
 * @private
 */
GeoJsonLoader.prototype.unload = function () {
  this._components = undefined;
};
<|endoftext|>


<commit_before>var define = define || function() {
};

define(function() {
   return TP_Server;
});

function TP_Server() {
   var self = this;

   // private vars
   var protocol = {
      request : {},
      response : {},
      struct : {},
      message : {},
      consts : {},
      reverseMap : {}
   };
   var requestCounter = 0;
   var requestHandlers = [];
   var messageHandlers = [];
   var openHandlers = [];
   var closeHandlers = [];
   var socket;
   var simulator = null;
   var lastHeardFrom = 0;

   // public interface
   self.commsLog = false;
   self.register = register;
   self.registerConst = registerConst;
   self.addMessageHandler = addMessageHandler;
   self.send = send;
   self.sendRequest = sendRequest;
   self.connect = connect;
   self.disconnect = disconnect;
   self.nameOf = nameOf;
   self.consts = protocol.consts;
   self.connected = false;
   self.setSimulator = function(s) {
      simulator = s;
   };

   for (var i = 0; i < arguments.length; i++) {
      new arguments[i](self);
   }

   function register(type, contractName, structName, contractId, structId) {
      var map = protocol[type];
      var val = {
         contractId : contractId,
         structId : structId
      };
      map[contractName + "." + structName] = val;
      if (map[structName]) {
         map[structName] = 0;
      } else {
         map[structName] = val;
      }
      protocol.reverseMap["" + contractId + "." + structId] = contractName + "." + structName;
   }

   function registerConst(contractName, structName, constName, constValue) {
      var map = protocol["consts"];
      var o;
      if (structName != null && structName != "null") {
         o = map[contractName + "." + structName] || {};
         map[contractName + "." + structName] = o;
      } else {
         o = map[contractName] || {};
         map[contractName] = o;
      }
      o[constName] = constValue;
   }

   function consts(name) {
      return protocol["consts"][name];
   }

   function nameOf(arg1, arg2) {
      // call with either a single arg = object with _contractId and _structId
      // or with explicit contractId, structId
      var key;
      if (typeof arg2 !== 'undefined') {
         key = "" + arg1 + "." + arg2;
      } else {
         key = "" + arg1._contractId + "." + arg1._structId;
      }
      return protocol.reverseMap[key];
   }

   function addMessageHandler(message, handler) {
      var val = protocol.message[message];
      if (!val) {
         console.log("unknown message: " + message);
         return;
      }
      if (val === 0) {
         console.log("ambiguous message: " + message);
         return;
      }
      messageHandlers[val.contractId + "." + val.structId] = handler;
   }

   function send(request, args, toId) {
      var val = protocol.request[request];
      if (!val) {
         console.log("unknown request: " + request);
         return;
      }
      if (val === 0) {
         console.log("ambiguous request: " + request);
         return;
      }
      return sendRequest(val.contractId, val.structId, args, toId);
   }

   function sendRequest(contractId, structId, args, toId) {
      toId = typeof toId !== 'undefined' ? toId : 0;
      var requestId = requestCounter++;
      args._requestId = requestId;
      args._contractId = contractId;
      args._structId = structId;
      args._toId = toId;
      if (self.commsLog)
         logRequest(args);

      if (simulator != null) {
         var resp = simulator.request(request, args, toId);
         var i;
         for (i = 0; i < resp.messages.length; i++) {
            var mess = resp.messages[i];
            handleMessage(mess);
         }
         return {
            handle : function(func) {
               requestHandlers[requestId] = func;
               handleResponse(resp.response);
            }
         }
      }

      if (socket && socket.readyState == WebSocket.OPEN) {
         socket.send(JSON.stringify(args, null, 3))
      }

      return {
         handle : function(func) {
            requestHandlers[requestId] = func;
         }
      }
   }

   function connect(server, secure, port) {
      port = typeof port !== 'undefined' ? port : window.location.port;
      if (!window.WebSocket) {
         window.WebSocket = window.MozWebSocket;
      }
      if (!window.WebSocket) {
         return null;
      }
      if (simulator != null) {
         return {
            listen : function(onOpen, onClose) {
               onOpen();
            }
         }
      }

      var url = (secure ? "wss:" : "ws:") + "//" + server + (port ? ":" + port : "") + "/sockets";
      console.log("Connecting to: " + url);
      socket = new WebSocket(url);
      socket.onopen = onSocketOpen;
      socket.onmessage = onSocketMessage;
      socket.onclose = onSocketClose;
      socket.onerror = onSocketError;
      return {
         listen : function(onOpen, onClose) {
            openHandlers = [];
            closeHandlers = [];
            openHandlers.push(onOpen);
            closeHandlers.push(onClose);
         }
      }
   }

   function disconnect() {
      if (self.commsLog)
         console.log("Disconnecting...");
      socket.close();
   }

   function logResponse(result) {
      var str = "";
      if (result.isError()) {
         str = "ERROR " + result.errorCode;
      } else if (result._contractId == 1 && result._structId == 2) {
         str = "SUCCESS";
      } else {
         str = JSON.stringify(result);
      }
      console.log("[%d] <- %s%s", result._requestId, nameOf(result), JSON.stringify(result, dropUnderscored));
   }

   function logRequest(result) {
      console.log("[%d] => %s%s", result._requestId, nameOf(result), JSON.stringify(result, dropUnderscored));
   }

   function logMessage(result) {
      console.log("[M:%d] <- %s%s", result._topicId, nameOf(result), JSON.stringify(result, dropUnderscored));
   }

   function dropUnderscored(key, value) {
      if (typeof key == 'string' || key instanceof String) {
         if (key.indexOf("_") == 0)
            return undefined;
      }
      return value;
   }

   function handleResponse(result) {
      result.isError = function() {
         return result._contractId == 1 && result._structId == 1;
      };
      if (self.commsLog)
         logResponse(result);
      var func = requestHandlers[result._requestId];
      if (func) {
         func(result);
      }
   }

   function handleMessage(result) {
      if (self.commsLog)
         logMessage(result);
      var func = messageHandlers[result._contractId + "." + result._structId];
      if (func) {
         func(result);
      }
   }

   // --- socket methods

   function onSocketOpen(event) {
      self.connected = true;
      if (self.commsLog)
         console.log("[socket] open: " + socket.URL);
      var i, array = openHandlers;
      for (i = 0; i < array.length; i++)
         array[i]();

      self.keepAlive = setInterval(function() {
         send("KeepAlive", {}, 1/* Core.DIRECT */);
         var elapsed = Date.now() - lastHeardFrom;
         if (elapsed > 6000) {
            console.log("We haven't heard from the server in " + elapsed + " ms")
            // TODO: mark as bad connection
         }
         if (elapsed > 20000) {
            disconnect();
         }
      }, 5000);

   }

   function onSocketClose(event) {
      self.connected = false;
      if (self.keepAlive != null) {
         clearInterval(self.keepAlive);
         self.keepAlive = null;
      }
      if (self.commsLog)
         console.log("[socket] closed")
      var i, array = closeHandlers;
      for (i = 0; i < array.length; i++)
         array[i]();
   }

   function onSocketMessage(event) {
      var result = null;
      if (event.data.indexOf("{") == 0) {
         result = JSON.parse(event.data);
      } else {
         // TODO figure out how to communicate errors
         result = parseInt(event.data);
      }
      if (result._requestId != null) {
         handleResponse(result);
      } else if (result._topicId != null) {
         handleMessage(result);
      }
      lastHeardFrom = Date.now();
   }

   function onSocketError(event) {
      if (self.commsLog)
         console.log("[socket] error: " + JSON.stringify(event));
   }

}
<commit_msg>st last heard from sooner<commit_after>var define = define || function() {
};

define(function() {
   return TP_Server;
});

function TP_Server() {
   var self = this;

   // private vars
   var protocol = {
      request : {},
      response : {},
      struct : {},
      message : {},
      consts : {},
      reverseMap : {}
   };
   var requestCounter = 0;
   var requestHandlers = [];
   var messageHandlers = [];
   var openHandlers = [];
   var closeHandlers = [];
   var socket;
   var simulator = null;
   var lastHeardFrom = 0;

   // public interface
   self.commsLog = false;
   self.register = register;
   self.registerConst = registerConst;
   self.addMessageHandler = addMessageHandler;
   self.send = send;
   self.sendRequest = sendRequest;
   self.connect = connect;
   self.disconnect = disconnect;
   self.nameOf = nameOf;
   self.consts = protocol.consts;
   self.connected = false;
   self.setSimulator = function(s) {
      simulator = s;
   };

   for (var i = 0; i < arguments.length; i++) {
      new arguments[i](self);
   }

   function register(type, contractName, structName, contractId, structId) {
      var map = protocol[type];
      var val = {
         contractId : contractId,
         structId : structId
      };
      map[contractName + "." + structName] = val;
      if (map[structName]) {
         map[structName] = 0;
      } else {
         map[structName] = val;
      }
      protocol.reverseMap["" + contractId + "." + structId] = contractName + "." + structName;
   }

   function registerConst(contractName, structName, constName, constValue) {
      var map = protocol["consts"];
      var o;
      if (structName != null && structName != "null") {
         o = map[contractName + "." + structName] || {};
         map[contractName + "." + structName] = o;
      } else {
         o = map[contractName] || {};
         map[contractName] = o;
      }
      o[constName] = constValue;
   }

   function consts(name) {
      return protocol["consts"][name];
   }

   function nameOf(arg1, arg2) {
      // call with either a single arg = object with _contractId and _structId
      // or with explicit contractId, structId
      var key;
      if (typeof arg2 !== 'undefined') {
         key = "" + arg1 + "." + arg2;
      } else {
         key = "" + arg1._contractId + "." + arg1._structId;
      }
      return protocol.reverseMap[key];
   }

   function addMessageHandler(message, handler) {
      var val = protocol.message[message];
      if (!val) {
         console.log("unknown message: " + message);
         return;
      }
      if (val === 0) {
         console.log("ambiguous message: " + message);
         return;
      }
      messageHandlers[val.contractId + "." + val.structId] = handler;
   }

   function send(request, args, toId) {
      var val = protocol.request[request];
      if (!val) {
         console.log("unknown request: " + request);
         return;
      }
      if (val === 0) {
         console.log("ambiguous request: " + request);
         return;
      }
      return sendRequest(val.contractId, val.structId, args, toId);
   }

   function sendRequest(contractId, structId, args, toId) {
      toId = typeof toId !== 'undefined' ? toId : 0;
      var requestId = requestCounter++;
      args._requestId = requestId;
      args._contractId = contractId;
      args._structId = structId;
      args._toId = toId;
      if (self.commsLog)
         logRequest(args);

      if (simulator != null) {
         var resp = simulator.request(request, args, toId);
         var i;
         for (i = 0; i < resp.messages.length; i++) {
            var mess = resp.messages[i];
            handleMessage(mess);
         }
         return {
            handle : function(func) {
               requestHandlers[requestId] = func;
               handleResponse(resp.response);
            }
         }
      }

      if (socket && socket.readyState == WebSocket.OPEN) {
         socket.send(JSON.stringify(args, null, 3))
      }

      return {
         handle : function(func) {
            requestHandlers[requestId] = func;
         }
      }
   }

   function connect(server, secure, port) {
      port = typeof port !== 'undefined' ? port : window.location.port;
      if (!window.WebSocket) {
         window.WebSocket = window.MozWebSocket;
      }
      if (!window.WebSocket) {
         return null;
      }
      if (simulator != null) {
         return {
            listen : function(onOpen, onClose) {
               onOpen();
            }
         }
      }

      var url = (secure ? "wss:" : "ws:") + "//" + server + (port ? ":" + port : "") + "/sockets";
      console.log("Connecting to: " + url);
      socket = new WebSocket(url);
      socket.onopen = onSocketOpen;
      socket.onmessage = onSocketMessage;
      socket.onclose = onSocketClose;
      socket.onerror = onSocketError;
      return {
         listen : function(onOpen, onClose) {
            openHandlers = [];
            closeHandlers = [];
            openHandlers.push(onOpen);
            closeHandlers.push(onClose);
         }
      }
   }

   function disconnect() {
      if (self.commsLog)
         console.log("Disconnecting...");
      socket.close();
   }

   function logResponse(result) {
      var str = "";
      if (result.isError()) {
         str = "ERROR " + result.errorCode;
      } else if (result._contractId == 1 && result._structId == 2) {
         str = "SUCCESS";
      } else {
         str = JSON.stringify(result);
      }
      console.log("[%d] <- %s%s", result._requestId, nameOf(result), JSON.stringify(result, dropUnderscored));
   }

   function logRequest(result) {
      console.log("[%d] => %s%s", result._requestId, nameOf(result), JSON.stringify(result, dropUnderscored));
   }

   function logMessage(result) {
      console.log("[M:%d] <- %s%s", result._topicId, nameOf(result), JSON.stringify(result, dropUnderscored));
   }

   function dropUnderscored(key, value) {
      if (typeof key == 'string' || key instanceof String) {
         if (key.indexOf("_") == 0)
            return undefined;
      }
      return value;
   }

   function handleResponse(result) {
      result.isError = function() {
         return result._contractId == 1 && result._structId == 1;
      };
      if (self.commsLog)
         logResponse(result);
      var func = requestHandlers[result._requestId];
      if (func) {
         func(result);
      }
   }

   function handleMessage(result) {
      if (self.commsLog)
         logMessage(result);
      var func = messageHandlers[result._contractId + "." + result._structId];
      if (func) {
         func(result);
      }
   }

   // --- socket methods

   function onSocketOpen(event) {
      lastHeardFrom = Date.now();
      self.connected = true;
      if (self.commsLog)
         console.log("[socket] open: " + socket.URL);
      var i, array = openHandlers;
      for (i = 0; i < array.length; i++)
         array[i]();

      self.keepAlive = setInterval(function() {
         send("KeepAlive", {}, 1/* Core.DIRECT */);
         var elapsed = Date.now() - lastHeardFrom;
         if (elapsed > 6000) {
            console.log("We haven't heard from the server in " + elapsed + " ms")
            // TODO: mark as bad connection
         }
         if (elapsed > 20000) {
            disconnect();
         }
      }, 5000);

   }

   function onSocketClose(event) {
      self.connected = false;
      if (self.keepAlive != null) {
         clearInterval(self.keepAlive);
         self.keepAlive = null;
      }
      if (self.commsLog)
         console.log("[socket] closed")
      var i, array = closeHandlers;
      for (i = 0; i < array.length; i++)
         array[i]();
   }

   function onSocketMessage(event) {
      lastHeardFrom = Date.now();
      var result = null;
      if (event.data.indexOf("{") == 0) {
         result = JSON.parse(event.data);
      } else {
         // TODO figure out how to communicate errors
         result = parseInt(event.data);
      }
      if (result._requestId != null) {
         handleResponse(result);
      } else if (result._topicId != null) {
         handleMessage(result);
      }
   }

   function onSocketError(event) {
      if (self.commsLog)
         console.log("[socket] error: " + JSON.stringify(event));
   }

}
<|endoftext|>


<commit_before>(function(){
	function ZgWaterfall(param){
		// this.__defaults = {
		// 	container: 'wf-container',
		// 	columns: 5,
		// 	colWidth:
		// };
		this.container = typeof param.container == 'string' ? document.getElementById(param.container) : param.container;
		this.colCount = param.colCount || 4;
		this.boxCls = param.boxCls && param.boxCls != '' ? param.boxCls : 'box';
		this.colWidth = Math.floor(this.container.offsetWidth / this.colCount) - 10; // 10为间隙
		this.init();
	}

	ZgWaterfall.prototype = {
		/**
		 * 通过父节点获取指定类名的所有孩子节点
		 * @param  {[type]} parent         父节点DOM对象
		 * @param  {[type]} childClassName 子节点类名
		 * @return {[type]}
		 */
		getChildElementByClassName: function(parent, childClassName){
			var childs = parent.getElementsByTagName('*');
			var boxes = [];
			for (var i = 0; i < childs.length; i++) {
				if(childs[i].className.indexOf(childClassName) != -1){
					boxes.push(childs[i]);
				}
			}
			return boxes;
		},
		/**
		 * 获取最小高度及其索引
		 * @param  {[type]} arr [description]
		 * @return {[type]}     [description]
		 */
		getMin: function(arr){
			// console.info(arr);
			var minColIndex = 0,
				minHeight = arr[0];
			for (var i = 0; i < arr.length; i++) {
				if(minHeight > arr[i]){
					minHeight = arr[i];
					minColIndex = i;
				}
			}
			return {height: minHeight, index: minColIndex};
		},
		/**
		 * 获取margin值
		 * @param  {[type]} node [description]
		 * @return {[type]}      [description]
		 */
		getMarginBottom:function(node){
	        var dis = 0;
	        if(node.currentStyle){
	            dis = parseInt(node.currentStyle.marginBottom);
	        }else if(document.defaultView){
	            dis = parseInt(document.defaultView.getComputedStyle(node,null).marginBottom);
	        }
	        return dis;
	    },
	    /**
	     * 获取最大高度
	     * @param  {[type]} arr [description]
	     * @return {[type]}     [description]
	     */
		getMaxheight: function(arr){
			var mh = arr[0];
			for (var i = 0; i < arr.length; i++) {
				if (mh < arr[i]) {
					mh = arr[i];
				}
			}
			return mh;
		},
		/**
		 * 初始化方法
		 */
		init: function(){
			var scope = this,
				i = 0,
				colHeightArr = [];	// 列高数组
			// 获取所有图片盒子
			var boxes = scope.getChildElementByClassName(scope.container, scope.boxCls);
			// 初始化列高、列索引数组
			for (i = 0; i < scope.colCount; i++) {
				colHeightArr[i] = 0;
			}
			for (i = 0; i < boxes.length; i++) {
				boxes[i].h = boxes[i].offsetHeight + scope.getMarginBottom(boxes[i]);
			}
			// 布置图片盒子
			for (i = 0; i < boxes.length; i++) {
				// 获取最小高度列索引及其最小高度
				var min = scope.getMin(colHeightArr);
				boxes[i].style.left = ((scope.colWidth + 10) * min.index) + 'px';
				boxes[i].style.top = min.height + 'px';
				colHeightArr[min.index] += boxes[i].h;
			}
			// 设置容器高度
			scope.container.style.height = scope.getMaxheight(colHeightArr) + 'px';
			scope.container.style.visibility = 'visible';
		}
	};

	window.onload = function(){
		new ZgWaterfall({
			container: 'wf_container',
			// colWidth: 240,	// 待扩展
			// gap: 10,			// 待扩展
		    colCount: 4,
		    boxCls: 'box'
		});
	};

})();

<commit_msg>update waterfall<commit_after>(function(){
	function ZgWaterfall(param){
		// this.__defaults = {
		// 	container: 'wf-container',
		// 	columns: 5,
		// 	colWidth:
		// };
		this.container = typeof param.container == 'string' ? document.getElementById(param.container) : param.container;
		this.colCount = param.colCount || 4;
		this.boxCls = param.boxCls && param.boxCls != '' ? param.boxCls : 'box';
		this.colWidth = Math.floor(this.container.offsetWidth / this.colCount) - 10; // 10为间隙
		this.lastBoxHeight = 0;
		this.init();
	}

	ZgWaterfall.prototype = {
		/**
		 * 通过父节点获取指定类名的所有孩子节点
		 * @param  {[type]} parent         父节点DOM对象
		 * @param  {[type]} childClassName 子节点类名
		 * @return {[type]}
		 */
		getChildElementByClassName: function(parent, childClassName){
			var childs = parent.getElementsByTagName('*');
			var boxes = [];
			for (var i = 0; i < childs.length; i++) {
				if(childs[i].className.indexOf(childClassName) != -1){
					boxes.push(childs[i]);
				}
			}
			return boxes;
		},
		/**
		 * 获取最小高度及其索引
		 * @param  {[type]} arr [description]
		 * @return {[type]}     [description]
		 */
		getMin: function(arr){
			// console.info(arr);
			var minColIndex = 0,
				minHeight = arr[0];
			for (var i = 0; i < arr.length; i++) {
				if(minHeight > arr[i]){
					minHeight = arr[i];
					minColIndex = i;
				}
			}
			return {height: minHeight, index: minColIndex};
		},
		/**
		 * 获取margin值
		 * @param  {[type]} node [description]
		 * @return {[type]}      [description]
		 */
		getMarginBottom:function(node){
	        var dis = 0;
	        if(node.currentStyle){
	            dis = parseInt(node.currentStyle.marginBottom);
	        }else if(document.defaultView){
	            dis = parseInt(document.defaultView.getComputedStyle(node,null).marginBottom);
	        }
	        return dis;
	    },
	    /**
	     * 获取最大高度
	     * @param  {[type]} arr [description]
	     * @return {[type]}     [description]
	     */
		getMaxheight: function(arr){
			var mh = arr[0];
			for (var i = 0; i < arr.length; i++) {
				if (mh < arr[i]) {
					mh = arr[i];
				}
			}
			return mh;
		},
		/**
		 * 当滚动到浏览器底端时加载图片
		 */
		addImg: function(){
			var scope = this;
			// 加载图片
			var data = {
				'root': [{'src': '4.jpg'},{'src': '14.jpg'},{'src': '5.jpg'},{'src': '15.jpg'},{'src': '6.jpg'},{'src': '16.jpg'},{'src': '7.jpg'},{'src': '17.jpg'},{'src': '8.jpg'},{'src': '18.jpg'}]
			};
			for (var i = 0; i < data.root.length; i++) {
				var box = document.createElement('div');
				box.className = 'box';
				var imgWrap = document.createElement('div');
				imgWrap.className = 'img-wrap';
				var img = document.createElement('img');
				img.src = 'img/' + data.root[i].src;
				imgWrap.appendChild(img);
				box.appendChild(imgWrap);
				scope.container.appendChild(box);
			}
			scope.init();
		},
		/**
		 * 初始化方法
		 */
		init: function(){
			var scope = this,
				i = 0,
				colHeightArr = [];	// 列高数组
			// 获取所有图片盒子
			var boxes = scope.getChildElementByClassName(scope.container, scope.boxCls);
			// 初始化列高、列索引数组
			for (i = 0; i < scope.colCount; i++) {
				colHeightArr[i] = 0;
			}
			for (i = 0; i < boxes.length; i++) {
				boxes[i].h = boxes[i].offsetHeight + scope.getMarginBottom(boxes[i]);
				scope.lastBoxHeight = boxes[boxes.length - 1].offsetHeight + scope.getMarginBottom(boxes[boxes.length - 1]);
			}
			// 布置图片盒子
			for (i = 0; i < boxes.length; i++) {
				// 获取最小高度列索引及其最小高度
				var min = scope.getMin(colHeightArr);
				boxes[i].style.left = ((scope.colWidth + 10) * min.index) + 'px';
				boxes[i].style.top = min.height + 'px';
				colHeightArr[min.index] += boxes[i].h;
			}
			// 设置容器高度
			scope.container.style.height = scope.getMaxheight(colHeightArr) + 'px';
			scope.container.style.visibility = 'visible';

			/**
			 * 滚动事件
			 * @return {[type]} [description]
			 */
			window.onscroll = function(){
				var st = document.documentElement.scrollTop || document.body.scrollTop;
				var sh = document.documentElement.scrollHeight || document.body.scrollHeight;
				var ch = document.documentElement.clientHeight ||  document.body.clientHeight;
				if(st + ch > sh - scope.lastBoxHeight) {
					console.log('aaa');
					scope.addImg();
				}
			};
		}
	};

	window.onload = function(){
		new ZgWaterfall({
			container: 'wf_container',
			// colWidth: 240,	// 待扩展
			// gap: 10,			// 待扩展
		    colCount: 4,
		    boxCls: 'box'
		});
	};

})();

<|endoftext|>