<commit_before>// This is the main application configuration file.  It is a Grunt
// configuration file, which you can learn more about here:
// https://github.com/cowboy/grunt/blob/master/docs/configuring.md

module.exports = function(grunt) {
  var path = require('path');
  var couch_config = {
    fauxton: {
              db: 'http://localhost:5984/fauxton',
              app: './couchapp.js',
              options: {
                okay_if_missing: true
              }
            }
  };

  function readSettingsFile () {
    if (path.existsSync("settings.json")) {
      return grunt.file.readJSON("settings.json")
    } else if (path.existsSync("settings.json.default")) {
      return grunt.file.readJSON("settings.json.default")
    } else {
      return {deps: []};
    }
  }

  function processAddons(callback){
    readSettingsFile().deps.forEach(callback);
  }

  var cleanable = function(){
    // Whitelist files and directories to be cleaned

    // You'll always want to clean these two directories
    var theListToClean = ["dist/", "app/load_addons.js"];
    // Now find the external addons you have and add them for cleaning up
    processAddons(function(addon){
      // Only clean addons that are included from a local dir
      if (addon.path){
        theListToClean.push("app/addons/" + addon.name);
      }
    });
    return theListToClean;
  }();

  var assets = function(){
    // Base assets
    var theAssets = {
      less:{
        paths: ["assets/less"],
        files: {
          "dist/debug/css/fauxton.css": "assets/less/fauxton.less"
        }
      },
      img: ["assets/img/**"]
    };
    processAddons(function(addon){
      // Less files from addons
      var root = addon.path || "app/addons/" + addon.name;
      var lessPath = root + "/assets/less";
      if(path.existsSync(lessPath)){
        // .less files exist for this addon
        theAssets.less.paths.push(lessPath);
        theAssets.less.files["dist/debug/css/" + addon.name + ".css"] =
            lessPath + "/" + addon.name + ".less";
      }
      // Images
      var root = addon.path || "app/addons/" + addon.name;
      var imgPath = root + "/assets/img";
      if(path.existsSync(imgPath)){
        theAssets.img.push(imgPath + "/**");
      }
    });
    grunt.log.write(theAssets.img[0]);
    return theAssets;
  }();

  var templateSettings = function(){
    var defaultSettings = {
      "src": "assets/index.underscore",
      "dest": "dist/debug/index.html",
      "variables": {
        "assets_root": "./",
        "requirejs": "require.js",
        "base": null
      }
    };
    var settings = grunt.file.readJSON("settings.json");
    return {template: settings.template || defaultSettings};
  }();

  grunt.initConfig({

    // The clean task ensures all files are removed from the dist/ directory so
    // that no files linger from previous builds.
    clean:  cleanable,

    // The lint task will run the build configuration and the application
    // JavaScript through JSHint and report any errors.  You can change the
    // options for this task, by reading this:
    // https://github.com/cowboy/grunt/blob/master/docs/task_lint.md
    lint: {
      files: [
        "build/config.js", "app/**/*.js"
      ]
    },

    less: {
      compile: {
        options: {
          paths: assets.less.paths
        },
        files: assets.less.files
      }
    },

    // The jshint option for scripturl is set to lax, because the anchor
    // override inside main.js needs to test for them so as to not accidentally
    // route.
    jshint: {
      options: {
        scripturl: true,
        evil: true
      }
    },

    // The jst task compiles all application templates into JavaScript
    // functions with the underscore.js template function from 1.2.4.  You can
    // change the namespace and the template options, by reading this:
    // https://github.com/gruntjs/grunt-contrib/blob/master/docs/jst.md
    //
    // The concat task depends on this file to exist, so if you decide to
    // remove this, ensure concat is updated accordingly.
    jst: {
      "dist/debug/templates.js": [
        "app/templates/**/*.html",
        "app/addons/**/templates/**/*.html"
      ]
    },

    // Create static html files from templates, for managing change of script
    // or css name.
    template: templateSettings,

    // The concatenate task is used here to merge the almond require/define
    // shim and the templates into the application code.  It's named
    // dist/debug/require.js, because we want to only load one script file in
    // index.html.
    concat: {
      requirejs: {
        src: ["assets/js/libs/almond.js", "dist/debug/templates.js", "dist/debug/require.js"],
        dest: "dist/debug/js/require.js"
      },

      debug: {
        src: ["dist/debug/css/*.css", 'assets/css/*.css'],
        dest: 'dist/debug/css/index.css'
      }

    },

    // This task uses the MinCSS Node.js project to take all your CSS files in
    // order and concatenate them into a single CSS file named index.css.  It
    // also minifies all the CSS as well.  This is named index.css, because we
    // only want to load one stylesheet in index.html.
    mincss: {
      "dist/release/css/index.css": [
        "dist/debug/css/index.css", 'assets/css/*.css',
        "app/addons/**/assets/css/*.css"
      ]
    },

    // Takes the built require.js file and minifies it for filesize benefits.
    min: {
      "dist/release/js/require.min.js": [
        "dist/debug/js/require.js"
      ]
    },

    // Running the server without specifying an action will run the defaults,
    // port: 8000 and host: 127.0.0.1.  If you would like to change these
    // defaults, simply add in the properties `port` and `host` respectively.
    // Alternatively you can omit the port and host properties and the server
    // task will instead default to process.env.PORT or process.env.HOST.
    //
    // Changing the defaults might look something like this:
    //
    // server: {
    //   host: "127.0.0.1", port: 9001
    //   debug: { ... can set host and port here too ...
    //  }
    //
    //  To learn more about using the server task, please refer to the code
    //  until documentation has been written.
    server: {
      // Ensure the favicon is mapped correctly.
      files: { "favicon.ico": "favicon.ico" },

      debug: {
        // Ensure the favicon is mapped correctly.
        "index": "./dist/debug/index.html",
        files: { "favicon.ico": "favicon.ico" },

        // Map `server:debug` to `debug` folders.
        folders: {
          "app": "dist/debug",
          "assets/js/libs": "dist/debug",
          "css": "dist/debug/css",
          "js": "dist/debug/js"
        }
      },

      proxies: {
        '': {
          host: 'localhost',
          port: 5984,
          https: false
        }
      },

      release: {
        // This makes it easier for deploying, by defaulting to any IP.
        host: "0.0.0.0",

        // Ensure the favicon is mapped correctly.
        files: { "favicon.ico": "favicon.ico" },

        // Map `server:release` to `release` folders.
        folders: {
          "app": "dist/release",
          "assets/js/libs": "dist/release",
          "assets/css": "dist/release"
        }
      }
    },

    // This task uses James Burke's excellent r.js AMD build tool.  In the
    // future other builders may be contributed as drop-in alternatives.
    requirejs: {
      // Include the main configuration file.
      mainConfigFile: "app/config.js",

      // Output file.
      out: "dist/debug/require.js",

      // Root application module.
      name: "config",

      // Do not wrap everything in an IIFE.
      wrap: false
    },

    // The headless QUnit testing environment is provided for "free" by Grunt.
    // Simply point the configuration to your test directory.
    qunit: {
      all: ["test/qunit/*.html"]
    },

    // The headless Jasmine testing is provided by grunt-jasmine-task. Simply
    // point the configuration to your test directory.
    jasmine: {
      all: ["test/jasmine/*.html"]
    },

    // Copy build artifacts and library code into the distribution

    copy: {
      couchdb: {
        files: {
          // this gets built in the template task
          //"../../share/www/fauxton/index.html": "dist/release/index.html",
          "../../share/www/fauxton/js/": "dist/release/js/**",
          // no images... yet
          "../../share/www/fauxton/img/": "dist/release/img/**",
          "../../share/www/fauxton/css/": "dist/release/css/**"
        }
      },
      couchdebug: {
        files: {
          // this gets built in the template task
          "../../share/www/fauxton/index.html": "dist/debug/index.html",
          "../../share/www/fauxton/js/": "dist/debug/js/**",
          // no images... yet
          "../../share/www/fauxton/img/": "dist/debug/img/**",
          "../../share/www/fauxton/css/": "dist/debug/css/**",
          // Must be possible to improve this...
          "../../share/www/fauxton/app/": "dist/debug/**"
        }
      },
      dist:{
        files:{
          "dist/release/js/": "assets/js/**",
          //"dist/release/css/**": "assets/css/**"
          "dist/release/img/": assets.img
        }
      },
      debug:{
        files:{
          "dist/debug/js/": "assets/js/**",
          //"dist/debug/css/": "dist/release/css/**"
          "dist/debug/img/": assets.img
        }
      }
    },

    get_deps: {
      "default": {
        src: "settings.json"
      }
    },

    gen_load_addons: {
      "default": {
        src: "settings.json"
      }
    },

    mkcouchdb: couch_config,
    rmcouchdb: couch_config,
    couchapp: couch_config

  });

  // Load fauxton specific tasks
  grunt.loadTasks('tasks');
  // Load the couchapp task
  grunt.loadNpmTasks('grunt-couchapp');
  // Load the copy task
  grunt.loadNpmTasks('grunt-contrib-copy');
  // Load the exec task
  grunt.loadNpmTasks('grunt-exec');

  // clean out previous build artefacts, lint and unit test
  grunt.registerTask('test', 'clean lint'); //qunit
  // Fetch dependencies (from git or local dir), lint them and make load_addons
  grunt.registerTask('dependencies', 'get_deps lint gen_load_addons:default');
  // build templates, js and css
  grunt.registerTask('build', 'jst requirejs concat:requirejs less');
  // minify code and css, ready for release.
  grunt.registerTask("minify", "min mincss");
  // deafult task - push to CouchDB
  grunt.registerTask("default", "test dependencies build release install");
  grunt.registerTask("dev", "debug server:debug");
  // make a debug install
  grunt.registerTask("debug", "test dependencies build template copy:debug concat:debug");
  // make an install that is server by mochiweb under _utils
  grunt.registerTask("couchdebug", "debug template copy:couchdebug");
  // make an install that can be deployed as a couchapp
  grunt.registerTask("couchapp_setup", "debug template");
  grunt.registerTask("couchdb", "test dependencies build minify template copy:couchdb");
  // build a release
  grunt.registerTask("release", "test dependencies build minify template copy:dist");
  // install fauxton as couchapp
  grunt.registerTask('couchapp_install', 'rmcouchdb:fauxton mkcouchdb:fauxton couchapp:fauxton');
  grunt.registerTask('couchapp_deploy', 'couchapp_setup couchapp_install');

};
<commit_msg>Use readSettingsFile function. Fix so checkout can build on jenkins<commit_after>// This is the main application configuration file.  It is a Grunt
// configuration file, which you can learn more about here:
// https://github.com/cowboy/grunt/blob/master/docs/configuring.md

module.exports = function(grunt) {
  var path = require('path');
  var couch_config = {
    fauxton: {
              db: 'http://localhost:5984/fauxton',
              app: './couchapp.js',
              options: {
                okay_if_missing: true
              }
            }
  };

  function readSettingsFile () {
    if (path.existsSync("settings.json")) {
      return grunt.file.readJSON("settings.json")
    } else if (path.existsSync("settings.json.default")) {
      return grunt.file.readJSON("settings.json.default")
    } else {
      return {deps: []};
    }
  }

  function processAddons(callback){
    readSettingsFile().deps.forEach(callback);
  }

  var cleanable = function(){
    // Whitelist files and directories to be cleaned

    // You'll always want to clean these two directories
    var theListToClean = ["dist/", "app/load_addons.js"];
    // Now find the external addons you have and add them for cleaning up
    processAddons(function(addon){
      // Only clean addons that are included from a local dir
      if (addon.path){
        theListToClean.push("app/addons/" + addon.name);
      }
    });
    return theListToClean;
  }();

  var assets = function(){
    // Base assets
    var theAssets = {
      less:{
        paths: ["assets/less"],
        files: {
          "dist/debug/css/fauxton.css": "assets/less/fauxton.less"
        }
      },
      img: ["assets/img/**"]
    };
    processAddons(function(addon){
      // Less files from addons
      var root = addon.path || "app/addons/" + addon.name;
      var lessPath = root + "/assets/less";
      if(path.existsSync(lessPath)){
        // .less files exist for this addon
        theAssets.less.paths.push(lessPath);
        theAssets.less.files["dist/debug/css/" + addon.name + ".css"] =
            lessPath + "/" + addon.name + ".less";
      }
      // Images
      var root = addon.path || "app/addons/" + addon.name;
      var imgPath = root + "/assets/img";
      if(path.existsSync(imgPath)){
        theAssets.img.push(imgPath + "/**");
      }
    });
    grunt.log.write(theAssets.img[0]);
    return theAssets;
  }();

  var templateSettings = function(){
    var defaultSettings = {
      "src": "assets/index.underscore",
      "dest": "dist/debug/index.html",
      "variables": {
        "assets_root": "./",
        "requirejs": "require.js",
        "base": null
      }
    };
    var settings = readSettingsFile();
    return {template: settings.template || defaultSettings};
  }();

  grunt.initConfig({

    // The clean task ensures all files are removed from the dist/ directory so
    // that no files linger from previous builds.
    clean:  cleanable,

    // The lint task will run the build configuration and the application
    // JavaScript through JSHint and report any errors.  You can change the
    // options for this task, by reading this:
    // https://github.com/cowboy/grunt/blob/master/docs/task_lint.md
    lint: {
      files: [
        "build/config.js", "app/**/*.js"
      ]
    },

    less: {
      compile: {
        options: {
          paths: assets.less.paths
        },
        files: assets.less.files
      }
    },

    // The jshint option for scripturl is set to lax, because the anchor
    // override inside main.js needs to test for them so as to not accidentally
    // route.
    jshint: {
      options: {
        scripturl: true,
        evil: true
      }
    },

    // The jst task compiles all application templates into JavaScript
    // functions with the underscore.js template function from 1.2.4.  You can
    // change the namespace and the template options, by reading this:
    // https://github.com/gruntjs/grunt-contrib/blob/master/docs/jst.md
    //
    // The concat task depends on this file to exist, so if you decide to
    // remove this, ensure concat is updated accordingly.
    jst: {
      "dist/debug/templates.js": [
        "app/templates/**/*.html",
        "app/addons/**/templates/**/*.html"
      ]
    },

    // Create static html files from templates, for managing change of script
    // or css name.
    template: templateSettings,

    // The concatenate task is used here to merge the almond require/define
    // shim and the templates into the application code.  It's named
    // dist/debug/require.js, because we want to only load one script file in
    // index.html.
    concat: {
      requirejs: {
        src: ["assets/js/libs/almond.js", "dist/debug/templates.js", "dist/debug/require.js"],
        dest: "dist/debug/js/require.js"
      },

      debug: {
        src: ["dist/debug/css/*.css", 'assets/css/*.css'],
        dest: 'dist/debug/css/index.css'
      }

    },

    // This task uses the MinCSS Node.js project to take all your CSS files in
    // order and concatenate them into a single CSS file named index.css.  It
    // also minifies all the CSS as well.  This is named index.css, because we
    // only want to load one stylesheet in index.html.
    mincss: {
      "dist/release/css/index.css": [
        "dist/debug/css/index.css", 'assets/css/*.css',
        "app/addons/**/assets/css/*.css"
      ]
    },

    // Takes the built require.js file and minifies it for filesize benefits.
    min: {
      "dist/release/js/require.min.js": [
        "dist/debug/js/require.js"
      ]
    },

    // Running the server without specifying an action will run the defaults,
    // port: 8000 and host: 127.0.0.1.  If you would like to change these
    // defaults, simply add in the properties `port` and `host` respectively.
    // Alternatively you can omit the port and host properties and the server
    // task will instead default to process.env.PORT or process.env.HOST.
    //
    // Changing the defaults might look something like this:
    //
    // server: {
    //   host: "127.0.0.1", port: 9001
    //   debug: { ... can set host and port here too ...
    //  }
    //
    //  To learn more about using the server task, please refer to the code
    //  until documentation has been written.
    server: {
      // Ensure the favicon is mapped correctly.
      files: { "favicon.ico": "favicon.ico" },

      debug: {
        // Ensure the favicon is mapped correctly.
        "index": "./dist/debug/index.html",
        files: { "favicon.ico": "favicon.ico" },

        // Map `server:debug` to `debug` folders.
        folders: {
          "app": "dist/debug",
          "assets/js/libs": "dist/debug",
          "css": "dist/debug/css",
          "js": "dist/debug/js"
        }
      },

      proxies: {
        '': {
          host: 'localhost',
          port: 5984,
          https: false
        }
      },

      release: {
        // This makes it easier for deploying, by defaulting to any IP.
        host: "0.0.0.0",

        // Ensure the favicon is mapped correctly.
        files: { "favicon.ico": "favicon.ico" },

        // Map `server:release` to `release` folders.
        folders: {
          "app": "dist/release",
          "assets/js/libs": "dist/release",
          "assets/css": "dist/release"
        }
      }
    },

    // This task uses James Burke's excellent r.js AMD build tool.  In the
    // future other builders may be contributed as drop-in alternatives.
    requirejs: {
      // Include the main configuration file.
      mainConfigFile: "app/config.js",

      // Output file.
      out: "dist/debug/require.js",

      // Root application module.
      name: "config",

      // Do not wrap everything in an IIFE.
      wrap: false
    },

    // The headless QUnit testing environment is provided for "free" by Grunt.
    // Simply point the configuration to your test directory.
    qunit: {
      all: ["test/qunit/*.html"]
    },

    // The headless Jasmine testing is provided by grunt-jasmine-task. Simply
    // point the configuration to your test directory.
    jasmine: {
      all: ["test/jasmine/*.html"]
    },

    // Copy build artifacts and library code into the distribution

    copy: {
      couchdb: {
        files: {
          // this gets built in the template task
          //"../../share/www/fauxton/index.html": "dist/release/index.html",
          "../../share/www/fauxton/js/": "dist/release/js/**",
          // no images... yet
          "../../share/www/fauxton/img/": "dist/release/img/**",
          "../../share/www/fauxton/css/": "dist/release/css/**"
        }
      },
      couchdebug: {
        files: {
          // this gets built in the template task
          "../../share/www/fauxton/index.html": "dist/debug/index.html",
          "../../share/www/fauxton/js/": "dist/debug/js/**",
          // no images... yet
          "../../share/www/fauxton/img/": "dist/debug/img/**",
          "../../share/www/fauxton/css/": "dist/debug/css/**",
          // Must be possible to improve this...
          "../../share/www/fauxton/app/": "dist/debug/**"
        }
      },
      dist:{
        files:{
          "dist/release/js/": "assets/js/**",
          //"dist/release/css/**": "assets/css/**"
          "dist/release/img/": assets.img
        }
      },
      debug:{
        files:{
          "dist/debug/js/": "assets/js/**",
          //"dist/debug/css/": "dist/release/css/**"
          "dist/debug/img/": assets.img
        }
      }
    },

    get_deps: {
      "default": {
        src: "settings.json"
      }
    },

    gen_load_addons: {
      "default": {
        src: "settings.json"
      }
    },

    mkcouchdb: couch_config,
    rmcouchdb: couch_config,
    couchapp: couch_config

  });

  // Load fauxton specific tasks
  grunt.loadTasks('tasks');
  // Load the couchapp task
  grunt.loadNpmTasks('grunt-couchapp');
  // Load the copy task
  grunt.loadNpmTasks('grunt-contrib-copy');
  // Load the exec task
  grunt.loadNpmTasks('grunt-exec');

  // clean out previous build artefacts, lint and unit test
  grunt.registerTask('test', 'clean lint'); //qunit
  // Fetch dependencies (from git or local dir), lint them and make load_addons
  grunt.registerTask('dependencies', 'get_deps lint gen_load_addons:default');
  // build templates, js and css
  grunt.registerTask('build', 'jst requirejs concat:requirejs less');
  // minify code and css, ready for release.
  grunt.registerTask("minify", "min mincss");
  // deafult task - push to CouchDB
  grunt.registerTask("default", "test dependencies build release install");
  grunt.registerTask("dev", "debug server:debug");
  // make a debug install
  grunt.registerTask("debug", "test dependencies build template copy:debug concat:debug");
  // make an install that is server by mochiweb under _utils
  grunt.registerTask("couchdebug", "debug template copy:couchdebug");
  // make an install that can be deployed as a couchapp
  grunt.registerTask("couchapp_setup", "debug template");
  grunt.registerTask("couchdb", "test dependencies build minify template copy:couchdb");
  // build a release
  grunt.registerTask("release", "test dependencies build minify template copy:dist");
  // install fauxton as couchapp
  grunt.registerTask('couchapp_install', 'rmcouchdb:fauxton mkcouchdb:fauxton couchapp:fauxton');
  grunt.registerTask('couchapp_deploy', 'couchapp_setup couchapp_install');

};
<|endoftext|>


<commit_before>/*
 * ESLinq - LINQ for EcmaScript 2015
 *
 * An easy and elegant way of working with iterables.
 *
 * Full source code and examples:
 * http://github.com/balazsbotond/eslinq
 */

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Botond Balazs <balazsbotond@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

"use strict";

/**
 * Helper function that wraps the specified iterable instance in an
 * ESLinq Collection which can be queried using ESLinq methods (like
 * 'select', 'where', etc.).
 *
 * @param {Iterable} iterable An iterable object (like an Array, a Set,
 *     or any object with a [Symbol.iterator] property).
 * @return {Collection} An ESLinq collection which can be queried using
 *     ESLinq methods (like 'select', 'where', etc.).
 *
 * @example
 * const numbers = [1, 2, 3, 4, 5];
 * const squaresOfEvenNumbers =
 *     from(numbers)
 *         .where(n => n % 2 === 0)
 *         .select(n => n * n);
 * for (let n of squaresOfEvenNumbers)
 *     console.log(n); // 4 16
 */
export default function from(iterable) {
    return new Collection(iterable);
}

/**
 * An iterable collection that can be queried using ESLinq methods (like
 * 'select', 'where', etc.).
 *
 * @implements {Iterable}
 */
export class Collection {
    constructor(iterable) {
        if (iterable instanceof Collection) iterable = iterable.iterable;

        this.iterable = iterable;
        this[Symbol.iterator] = iterable[Symbol.iterator];
    }

    /*
     * Projection and restriction methods
     */

    /**
     * Applies the specified transformation to all elements of the
     * Collection, returning a new Collection of the transformed elements.
     *
     * @param {function(i: any): any} transform A function that is used
     *     to transform the elements of the collection.
     * @return {Collection} A new Collection of the transformed elements.
     *
     * @example
     * const numbers = [1, 2, 3, 4, 5];
     * const even = from(numbers).select(n => n % 2 === 0);
     * for (let n of even) console.log(n); // 2 4
     */
    select(transform) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            for (let i of iterable) yield transform(i);
        });
    }

    /**
     * Applies the specified transformation to all elements of the
     * Collection. The transformation should return an iterable. The
     * resulting collection will be a concatenation of these iterables.
     *
     * @param {function(i: any): Iterable} transform A function that is
     *     called for each Collection element. Should return a iterable.
     * @return {Collection} A concatenation of the iterables returned by
     *     the transformation function.
     * @throws {Error} If the object returned by the transform function
     *     is not iterable.
     *
     * @example
     * const taskLists = [
     *     {tasks: [1]}, {tasks: [2, 3]}, {tasks: [4]},
     *     {tasks: []}, {tasks: [5]}
     * ];
     * const allTasks = from(taskLists).selectMany(t => t.tasks);
     * for (let t of allTasks) console.log(t); // 1 2 3 4 5
     */
    selectMany(transform) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            for (let i of iterable) {
                const innerIter = transform(i);
                ensureIsIterable(innerIter, "Transform function should return an iterable");
                for (let j of innerIter) yield j;
            }
        });
    }

    /**
     * Filters the Collection by a condition specified.
     *
     * @param {function(i: any): boolean} matches A function that returns
     *     true if an element is to be included in the result.
     * @return {Collection} A Collection of the elements for which the
     *     'matches' function returned true.
     *
     * @example
     * const numbers = [1, 2, 3, 4, 5];
     * const even = from(numbers).where(n => n % 2 === 0);
     * for (let n of even) console.log(n); // 2 4
     */
    where(matches) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            for (let i of iterable) if (matches(i)) yield i;
        });
    }

    /*
     * Join methods
     */

    /*
     * Set methods
     */

    /**
     * Determines whether all elements satisfy a condition.
     *
     * @param {function(i: any): boolean} matches A function that
     *     determines whether an element of the Collection satisfies
     *     a condition.
     * @return {boolean} true if all elements satisfy the condition,
     *     otherwise, false.
     *
     * @example
     * const numbers = [1, 2, 3],
     *       even = [2, 4, 6],
     *       isEven = n => n % 2 === 0;
     * from(numbers).all(isEven); // false
     * from(even).all(isEven); // true
     */
    all(matches) {
        for (let i of this.iterable) if (!matches(i)) return false;
        return true;
    }

    /**
     * Determines whether at least one element satisfies a condition.
     *
     * @param {function(i: any): boolean} matches A function that
     *     determines whether an element of the Collection satisfies
     *     a condition.
     * @return {boolean} true if at least one element satisfies the
     *     condition, otherwise, false.
     *
     * @example
     * const numbers = [1, 2, 3],
     *       even = [2, 4, 6],
     *       isOdd = n => n % 2 !== 0;
     * from(numbers).any(isOdd); // true
     * from(even).any(isOdd); // false
     */
    any(matches = _ => true) {
        for (let i of this.iterable) if (matches(i)) return true;
        return false;
    }

    /**
     * Determines whether at least one element is equal to the item specified
     * using the strict equality operator.
     *
     * @param {any} item The item to find.
     * @return {boolean} true if at least one element is equal to the item
     *     specified, otherwise, false.
     *
     * @example
     * const numbers = [1, 2, 3];
     * from(numbers).contains(n => n % 2 === 0); // true, 2 is even
     * from(numbers).contains(n => n > 3); // false, all elements less than 3
     */
    contains(item) {
        for (let i of this.iterable) if (i === item) return true;
        return false;
    }

    /**
     * Concatenates the iterable specified with the current one.
     *
     * @param {Iterable} other The iterable to concatenate after this instance.
     * @return {Collection} The concatenation of the two iterables.
     *
     * @example
     * const numbers = [1, 2],
     *       letters = ["a", "b"],
     *       result  = from(numbers).concat(letters);
     * for (let i of result) console.log(i); // 1 2 a b
     */
    concat(other) {
        const self = this;
        return this._spawn(function* () {
            for (let i of self.iterable) yield i;
            for (let j of other) yield j;
        });
    }

    /**
     * Returns the distinct elements in the collection (removes duplication).
     *
     * @return {Collection} A Collection containing the distinct elements
     *     of the original one.
     *
     * @example
     * const numbers = [1, 1, 1, 2, 3, 4, 3],
     *       noDupl = from(numbers).distinct();
     * for (let n of noDupl) console.log(n); // 1 2 3 4
     */
    distinct() {
        return new Collection(new Set(this.iterable));
    }

    except(other) {
        const iterable = this.iterable;
        other = new Collection(other);
        return this._spawn(function* () {
            for (let i of iterable) if (!other.contains(i)) yield i;
        });
    }

    intersect(other) {
        const iterable = this.iterable;
        other = new Collection(other);
        return this._spawn(function* () {
           for (let i of iterable) if (other.contains(i)) yield i;
        });
    }

    union(other) {
        return new Collection(this.iterable).concat(other).distinct();
    }

    /*
     * Ordering methods
     */

     orderBy(get, compare = compareDefault) {
        let result = Array.from(this.iterable);
        result.sort((a, b) => compare(get(a), get(b)));
        return new Collection(result);
     }

     orderByDescending(get, compare = compareDefault) {
        let result = Array.from(this.iterable);
        result.sort((a, b) => compare(get(b), get(a)));
        return new Collection(result);
     }

     reverse() {
        const array = Array.from(this.iterable);
        return this._spawn(function* () {
            for (let i = array.length - 1; i >= 0; i--) yield array[i];
        });
     }

    /*
     * Grouping methods
     */

    groupBy(getKey) {
        const map = new Map();
        for (let i of this.iterable) {
            const key = getKey(i);
            if (map.has(key)) map.get(key).push(i);
            else map.set(getKey(i), [i]);
        }
        return new Collection(map);
    }

    /*
     * Aggregate methods
     */

    aggregate(aggr) {
        let acc;
        for (let i of this.iterable) acc = !acc ? i : aggr(acc, i);
        return acc;
    }

    average(select = n => n) {
        let sum = 0, count = 0;
        for (let i of this.iterable) {
            this._ensureIsNumber(i);
            sum += select(i);
            count++;
        }
        return sum / count;
    }

    sum(select = n => n) {
        let sum;
        for (let i of this.iterable) {
            this._ensureIsNumber(i);
            sum += select(i);
        }
        return sum;
    }

    count(matches = _ => true) {
        let count = 0;
        for (let i of this.iterable) if (matches(i)) count++;
        return count;
    }

    /*
     * Paging methods
     */

    elementAt(index) {
        ensureNotNegative(index, "index");
        const element = this._elementAt(index);
        ensureIsDefined(element, "Index too large");
        return element;
    }

    elementAtOrDefault(index, defaultValue) {
        ensureNotNegative(index, "index");
        const element = this._elementAt(index);
        return element !== undefined ? element : defaultValue;
    }

    _elementAt(index) {
        let i = 0;
        for (let item of this.iterable) {
            if (i === index) return i;
            i++;
        }
        return undefined;
    }

    first(matches = _ => true) {
        for (let i of this.iterable) if (matches(i)) return i;
        throw "No matching element found";
    }

    firstOrDefault(matches = _ => true, defaultValue) {
        for (let i of this.iterable) if (matches(i)) return i;
        return defaultValue;
    }

    last(matches = _ => true) {
        const result = this._last(matches);
        if (!result.found)
            throw "No matching element found";
        return result.item;
    }

    lastOrDefault(matches = _ => true, defaultValue) {
        const result = this._last(matches);
        if (!result.found)
            return defaultValue;
        return result.item;
    }

    _last(matches = _ => true) {
        let found = false, item;
        for (let i of this.iterable)
            if (matches(i)) { item = i; found = true; }
        return { found, item };
    }

    single(matches = _ => true) {
        const result = this._single(matches);
        if (!result.found)
            throw "No matching element found";
        return result.item;
    }

    singleOrDefault(matches = _ => true, defaultValue) {
        const result = this._single(matches);
        if (!result.found)
            return defaultValue;
        return result.item;
    }

    _single(matches = _ => true) {
        let found = false, item;
        for (let i of this.iterable) {
            if (matches(i)) {
                if (found)
                    throw "Collection contains more than one matching element";
                item = i;
                found = true;
            }
        }
        return { found, item };
    }

    skip(count) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            let c = 0;
            for (let i of iterable) if (++c > count) yield i;
        });
    }

    skipWhile(matches) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            let wasFalse = false;
            for (let i of iterable) {
                if (wasFalse || !matches(i)) {
                    wasFalse = true;
                    yield i;
                }
            }
        });
    }

    take(count) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            let c = 0;
            for (let i of iterable) {
                if (++c <= count) yield i;
                else break;
            }
        });
    }

    takeWhile(matches) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            for (let i of iterable) {
                if (matches(i)) yield i;
                else break;
            }
        });
    }

    /*
     * Conversion methods
     */

    toArray() {
        return Array.from(this.iterable);
    }

    /*
     * Private helpers
     */

    _spawn(generator) {
        return new Collection({ [Symbol.iterator]: generator });
    }

    _log() {
        for (let i of this.iterable) console.log(i);
    }
}

/*
 * Functions used as default arguments
 */

function compareDefault(a, b) {
    if (a < b) return -1;
    if (a > b) return 1;
    return 0;
}

/*
 * Argument validation helpers
 */

function ensureIsNumber(n) {
    if (typeof n !== "number")
        throw new Error("Only numbers can be averaged");
}

function ensureNotNegative(n, name) {
    if (n < 0) throw new Error(`${name} must not be negative`);
}

function ensureIsDefined(x, message) {
    if (x === undefined) throw new Error(message);
}

function ensureIsFunction(f, message) {
    if (typeof f !== "function") throw new Error(message);
}

function ensureIsIterable(i, message) {
    const iter = i[Symbol.iterator];
    ensureIsDefined(iter, message);
    ensureIsFunction(iter, message);
}
<commit_msg>Documentation for 'except'<commit_after>/*
 * ESLinq - LINQ for EcmaScript 2015
 *
 * An easy and elegant way of working with iterables.
 *
 * Full source code and examples:
 * http://github.com/balazsbotond/eslinq
 */

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Botond Balazs <balazsbotond@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

"use strict";

/**
 * Helper function that wraps the specified iterable instance in an
 * ESLinq Collection which can be queried using ESLinq methods (like
 * 'select', 'where', etc.).
 *
 * @param {Iterable} iterable An iterable object (like an Array, a Set,
 *     or any object with a [Symbol.iterator] property).
 * @return {Collection} An ESLinq collection which can be queried using
 *     ESLinq methods (like 'select', 'where', etc.).
 *
 * @example
 * const numbers = [1, 2, 3, 4, 5];
 * const squaresOfEvenNumbers =
 *     from(numbers)
 *         .where(n => n % 2 === 0)
 *         .select(n => n * n);
 * for (let n of squaresOfEvenNumbers)
 *     console.log(n); // 4 16
 */
export default function from(iterable) {
    return new Collection(iterable);
}

/**
 * An iterable collection that can be queried using ESLinq methods (like
 * 'select', 'where', etc.).
 *
 * @implements {Iterable}
 */
export class Collection {
    constructor(iterable) {
        if (iterable instanceof Collection) iterable = iterable.iterable;

        this.iterable = iterable;
        this[Symbol.iterator] = iterable[Symbol.iterator];
    }

    /*
     * Projection and restriction methods
     */

    /**
     * Applies the specified transformation to all elements of the
     * Collection, returning a new Collection of the transformed elements.
     *
     * @param {function(i: any): any} transform A function that is used
     *     to transform the elements of the collection.
     * @return {Collection} A new Collection of the transformed elements.
     *
     * @example
     * const numbers = [1, 2, 3, 4, 5];
     * const even = from(numbers).select(n => n % 2 === 0);
     * for (let n of even) console.log(n); // 2 4
     */
    select(transform) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            for (let i of iterable) yield transform(i);
        });
    }

    /**
     * Applies the specified transformation to all elements of the
     * Collection. The transformation should return an iterable. The
     * resulting collection will be a concatenation of these iterables.
     *
     * @param {function(i: any): Iterable} transform A function that is
     *     called for each Collection element. Should return a iterable.
     * @return {Collection} A concatenation of the iterables returned by
     *     the transformation function.
     * @throws {Error} If the object returned by the transform function
     *     is not iterable.
     *
     * @example
     * const taskLists = [
     *     {tasks: [1]}, {tasks: [2, 3]}, {tasks: [4]},
     *     {tasks: []}, {tasks: [5]}
     * ];
     * const allTasks = from(taskLists).selectMany(t => t.tasks);
     * for (let t of allTasks) console.log(t); // 1 2 3 4 5
     */
    selectMany(transform) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            for (let i of iterable) {
                const innerIter = transform(i);
                ensureIsIterable(innerIter, "Transform function should return an iterable");
                for (let j of innerIter) yield j;
            }
        });
    }

    /**
     * Filters the Collection by a condition specified.
     *
     * @param {function(i: any): boolean} matches A function that returns
     *     true if an element is to be included in the result.
     * @return {Collection} A Collection of the elements for which the
     *     'matches' function returned true.
     *
     * @example
     * const numbers = [1, 2, 3, 4, 5];
     * const even = from(numbers).where(n => n % 2 === 0);
     * for (let n of even) console.log(n); // 2 4
     */
    where(matches) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            for (let i of iterable) if (matches(i)) yield i;
        });
    }

    /*
     * Join methods
     */

    /*
     * Set methods
     */

    /**
     * Determines whether all elements satisfy a condition.
     *
     * @param {function(i: any): boolean} matches A function that
     *     determines whether an element of the Collection satisfies
     *     a condition.
     * @return {boolean} true if all elements satisfy the condition,
     *     otherwise, false.
     *
     * @example
     * const numbers = [1, 2, 3],
     *       even = [2, 4, 6],
     *       isEven = n => n % 2 === 0;
     * from(numbers).all(isEven); // false
     * from(even).all(isEven); // true
     */
    all(matches) {
        for (let i of this.iterable) if (!matches(i)) return false;
        return true;
    }

    /**
     * Determines whether at least one element satisfies a condition.
     *
     * @param {function(i: any): boolean} matches A function that
     *     determines whether an element of the Collection satisfies
     *     a condition.
     * @return {boolean} true if at least one element satisfies the
     *     condition, otherwise, false.
     *
     * @example
     * const numbers = [1, 2, 3],
     *       even = [2, 4, 6],
     *       isOdd = n => n % 2 !== 0;
     * from(numbers).any(isOdd); // true
     * from(even).any(isOdd); // false
     */
    any(matches = _ => true) {
        for (let i of this.iterable) if (matches(i)) return true;
        return false;
    }

    /**
     * Determines whether at least one element is equal to the item specified
     * using the strict equality operator.
     *
     * @param {any} item The item to find.
     * @return {boolean} true if at least one element is equal to the item
     *     specified, otherwise, false.
     *
     * @example
     * const numbers = [1, 2, 3];
     * from(numbers).contains(n => n % 2 === 0); // true, 2 is even
     * from(numbers).contains(n => n > 3); // false, all elements less than 3
     */
    contains(item) {
        for (let i of this.iterable) if (i === item) return true;
        return false;
    }

    /**
     * Concatenates the iterable specified with the current one.
     *
     * @param {Iterable} other The iterable to concatenate after this instance.
     * @return {Collection} The concatenation of the two iterables.
     *
     * @example
     * const numbers = [1, 2],
     *       letters = ["a", "b"],
     *       result  = from(numbers).concat(letters);
     * for (let i of result) console.log(i); // 1 2 a b
     */
    concat(other) {
        const self = this;
        return this._spawn(function* () {
            for (let i of self.iterable) yield i;
            for (let j of other) yield j;
        });
    }

    /**
     * Returns the distinct elements in the collection (removes duplication).
     *
     * @return {Collection} A Collection containing the distinct elements
     *     of the original one.
     *
     * @example
     * const numbers = [1, 1, 1, 2, 3, 4, 3],
     *       noDupl = from(numbers).distinct();
     * for (let n of noDupl) console.log(n); // 1 2 3 4
     */
    distinct() {
        return new Collection(new Set(this.iterable));
    }

    /**
     * Returns all elements of the iterable except the ones in `other`.
     *
     * @param {Iterable} other The iterable to be subtracted.
     * @return All elements of the iterable except the ones in `other`.
     *
     * @example
     * const numbers = [1, 2, 3, 4, 5],
     *       exceptions = [3, 4],
     *       difference = from(numbers).except(exceptions);
     * for (let n of difference) console.log(n); // 1 2 5
     */
    except(other) {
        const iterable = this.iterable;
        other = new Collection(other);
        return this._spawn(function* () {
            // TODO: this is a very naive implementation. We should build
            // a set from `other` and use that for the lookup.
            for (let i of iterable) if (!other.contains(i)) yield i;
        });
    }

    intersect(other) {
        const iterable = this.iterable;
        other = new Collection(other);
        return this._spawn(function* () {
           for (let i of iterable) if (other.contains(i)) yield i;
        });
    }

    union(other) {
        return new Collection(this.iterable).concat(other).distinct();
    }

    /*
     * Ordering methods
     */

     orderBy(get, compare = compareDefault) {
        let result = Array.from(this.iterable);
        result.sort((a, b) => compare(get(a), get(b)));
        return new Collection(result);
     }

     orderByDescending(get, compare = compareDefault) {
        let result = Array.from(this.iterable);
        result.sort((a, b) => compare(get(b), get(a)));
        return new Collection(result);
     }

     reverse() {
        const array = Array.from(this.iterable);
        return this._spawn(function* () {
            for (let i = array.length - 1; i >= 0; i--) yield array[i];
        });
     }

    /*
     * Grouping methods
     */

    groupBy(getKey) {
        const map = new Map();
        for (let i of this.iterable) {
            const key = getKey(i);
            if (map.has(key)) map.get(key).push(i);
            else map.set(getKey(i), [i]);
        }
        return new Collection(map);
    }

    /*
     * Aggregate methods
     */

    aggregate(aggr) {
        let acc;
        for (let i of this.iterable) acc = !acc ? i : aggr(acc, i);
        return acc;
    }

    average(select = n => n) {
        let sum = 0, count = 0;
        for (let i of this.iterable) {
            this._ensureIsNumber(i);
            sum += select(i);
            count++;
        }
        return sum / count;
    }

    sum(select = n => n) {
        let sum;
        for (let i of this.iterable) {
            this._ensureIsNumber(i);
            sum += select(i);
        }
        return sum;
    }

    count(matches = _ => true) {
        let count = 0;
        for (let i of this.iterable) if (matches(i)) count++;
        return count;
    }

    /*
     * Paging methods
     */

    elementAt(index) {
        ensureNotNegative(index, "index");
        const element = this._elementAt(index);
        ensureIsDefined(element, "Index too large");
        return element;
    }

    elementAtOrDefault(index, defaultValue) {
        ensureNotNegative(index, "index");
        const element = this._elementAt(index);
        return element !== undefined ? element : defaultValue;
    }

    _elementAt(index) {
        let i = 0;
        for (let item of this.iterable) {
            if (i === index) return i;
            i++;
        }
        return undefined;
    }

    first(matches = _ => true) {
        for (let i of this.iterable) if (matches(i)) return i;
        throw "No matching element found";
    }

    firstOrDefault(matches = _ => true, defaultValue) {
        for (let i of this.iterable) if (matches(i)) return i;
        return defaultValue;
    }

    last(matches = _ => true) {
        const result = this._last(matches);
        if (!result.found)
            throw "No matching element found";
        return result.item;
    }

    lastOrDefault(matches = _ => true, defaultValue) {
        const result = this._last(matches);
        if (!result.found)
            return defaultValue;
        return result.item;
    }

    _last(matches = _ => true) {
        let found = false, item;
        for (let i of this.iterable)
            if (matches(i)) { item = i; found = true; }
        return { found, item };
    }

    single(matches = _ => true) {
        const result = this._single(matches);
        if (!result.found)
            throw "No matching element found";
        return result.item;
    }

    singleOrDefault(matches = _ => true, defaultValue) {
        const result = this._single(matches);
        if (!result.found)
            return defaultValue;
        return result.item;
    }

    _single(matches = _ => true) {
        let found = false, item;
        for (let i of this.iterable) {
            if (matches(i)) {
                if (found)
                    throw "Collection contains more than one matching element";
                item = i;
                found = true;
            }
        }
        return { found, item };
    }

    skip(count) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            let c = 0;
            for (let i of iterable) if (++c > count) yield i;
        });
    }

    skipWhile(matches) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            let wasFalse = false;
            for (let i of iterable) {
                if (wasFalse || !matches(i)) {
                    wasFalse = true;
                    yield i;
                }
            }
        });
    }

    take(count) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            let c = 0;
            for (let i of iterable) {
                if (++c <= count) yield i;
                else break;
            }
        });
    }

    takeWhile(matches) {
        const iterable = this.iterable;
        return this._spawn(function* () {
            for (let i of iterable) {
                if (matches(i)) yield i;
                else break;
            }
        });
    }

    /*
     * Conversion methods
     */

    toArray() {
        return Array.from(this.iterable);
    }

    /*
     * Private helpers
     */

    _spawn(generator) {
        return new Collection({ [Symbol.iterator]: generator });
    }

    _log() {
        for (let i of this.iterable) console.log(i);
    }
}

/*
 * Functions used as default arguments
 */

function compareDefault(a, b) {
    if (a < b) return -1;
    if (a > b) return 1;
    return 0;
}

/*
 * Argument validation helpers
 */

function ensureIsNumber(n) {
    if (typeof n !== "number")
        throw new Error("Only numbers can be averaged");
}

function ensureNotNegative(n, name) {
    if (n < 0) throw new Error(`${name} must not be negative`);
}

function ensureIsDefined(x, message) {
    if (x === undefined) throw new Error(message);
}

function ensureIsFunction(f, message) {
    if (typeof f !== "function") throw new Error(message);
}

function ensureIsIterable(i, message) {
    const iter = i[Symbol.iterator];
    ensureIsDefined(iter, message);
    ensureIsFunction(iter, message);
}
<|endoftext|>


<commit_before>import Rx from 'rx'
let fromEvent = Rx.Observable.fromEvent
let Observable = Rx.Observable
let merge = Rx.Observable.merge

import logger from 'log-minim'
let log = logger("app")
log.setLevel("debug")

import {generateUUID, nameCleanup} from 'usco-kernel2/src/utils'
import {computeBoundingBox,computeBoundingSphere} from 'glView-helpers/src/meshTools/computeBounds'

const defaults = {
  partTypes:[],
  meshNameToPartTypeUId:{},
  typeUidToMeshName:{},
  typeData:{},
  latest:undefined,

  //not sure
  typeUidToTemplateMesh:{}
}

function makeModifications(intent){
  let registerTypeFromMesh$ = intent.combos$
    .map((data) => (regData) => {
      log.info("I would register something", data, regData)

      //we do not return the shape since that becomes the "reference shape/mesh", not the
      //one that will be shown
      //return partKlass

      let partTypes = regData.partTypes || []
      let meshNameToPartTypeUId = regData.meshNameToPartTypeUId || {}
      let typeUidToMeshName = regData.typeUidToMeshName || {}
      let typeData = regData.typeData || {}

      let meshName      = data.resource.name || ""
      let cleanedName   = nameCleanup(meshName)
      let typeUid = meshNameToPartTypeUId[ meshName ]

      let typeUidToTemplateMesh = regData.typeUidToTemplateMesh || {}

      //no typeUid was given, it means we have a mesh with no part (yet !)
      if( !typeUid ) {
        typeUid = generateUUID()
        //typeUid = "A0"

        //extract usefull information
        let mesh = data.mesh
        computeBoundingSphere(mesh)
        computeBoundingBox(mesh)
        typeData[typeUid]={
          name:cleanedName,
          bbox:{
            min: mesh.boundingBox.min.toArray(),
            max: mesh.boundingBox.max.toArray()
          }
        }
        //console.log("mesh bb",mesh.boundingBox)

        //create ...
        //partKlass = this.makeNamedPartKlass( cleanedName, typeUid )
        //& register class

        partTypes.push(typeUid)
        meshNameToPartTypeUId[meshName] = typeUid
        typeUidToMeshName[typeUid] = meshName

        typeUidToTemplateMesh[typeUid] = mesh
      }

      return {
        partTypes,
        meshNameToPartTypeUId,
        typeUidToMeshName,
        typeData,
        latest:typeUid,

        typeUidToTemplateMesh
      }
  })

  /*technically same as deleteAll , but kept seperate for clarity*/
  let clearData$ = intent.deleteAllEntities$
    .map(() => (regData) => {
      log.info("New design, clearing registry",regData)
      return Object.assign({},defaults)
      //return regData
  })

  return merge(
    registerTypeFromMesh$
    ,clearData$
  )
}

function model(intent, source) {
  let source$ = source || Observable.just(defaults)

  let modification$ = makeModifications(intent)

  return modification$
    .merge(source$)
    .scan((regData, modFn) => modFn(regData))//combine existing data with new one
    .shareReplay(1)
}

export default model<commit_msg>- clearer naming of model for partReg<commit_after>import Rx from 'rx'
let fromEvent = Rx.Observable.fromEvent
let Observable = Rx.Observable
let merge = Rx.Observable.merge

import logger from 'log-minim'
let log = logger("app")
log.setLevel("debug")

import {generateUUID, nameCleanup} from 'usco-kernel2/src/utils'
import {computeBoundingBox,computeBoundingSphere} from 'glView-helpers/src/meshTools/computeBounds'

const defaults = {
  partTypes:[],
  meshNameToPartTypeUId:{},
  typeUidToMeshName:{},
  typeData:{},
  latest:undefined,

  //not sure
  typeUidToTemplateMesh:{}
}

function makeModifications(intent){
  let registerTypeFromMesh$ = intent.combos$
    .map((data) => (regData) => {
      log.info("I would register something", data, regData)

      //we do not return the shape since that becomes the "reference shape/mesh", not the
      //one that will be shown
      //return partKlass

      let partTypes = regData.partTypes || []
      let meshNameToPartTypeUId = regData.meshNameToPartTypeUId || {}
      let typeUidToMeshName = regData.typeUidToMeshName || {}
      let typeData = regData.typeData || {}

      let meshName      = data.resource.name || ""
      let cleanedName   = nameCleanup(meshName)
      let typeUid = meshNameToPartTypeUId[ meshName ]

      let typeUidToTemplateMesh = regData.typeUidToTemplateMesh || {}

      //no typeUid was given, it means we have a mesh with no part (yet !)
      if( !typeUid ) {
        typeUid = generateUUID()
        //typeUid = "A0"

        //extract usefull information
        let mesh = data.mesh
        computeBoundingSphere(mesh)
        computeBoundingBox(mesh)
        typeData[typeUid]={
          name:cleanedName,
          bbox:{
            min: mesh.boundingBox.min.toArray(),
            max: mesh.boundingBox.max.toArray()
          }
        }
        //console.log("mesh bb",mesh.boundingBox)

        //create ...
        //partKlass = this.makeNamedPartKlass( cleanedName, typeUid )
        //& register class

        partTypes.push(typeUid)
        meshNameToPartTypeUId[meshName] = typeUid
        typeUidToMeshName[typeUid] = meshName

        typeUidToTemplateMesh[typeUid] = mesh
      }

      return {
        partTypes,
        meshNameToPartTypeUId,
        typeUidToMeshName,
        typeData,
        latest:typeUid,

        typeUidToTemplateMesh
      }
  })

  /*technically same as deleteAll , but kept seperate for clarity*/
  let clearData$ = intent.deleteAllEntities$
    .map(() => (regData) => {
      log.info("New design, clearing registry",regData)
      return Object.assign({},defaults)
      //return regData
  })

  return merge(
    registerTypeFromMesh$
    ,clearData$
  )
}

function partReg(intent, source) {
  let source$ = source || Observable.just(defaults)

  let modification$ = makeModifications(intent)

  return modification$
    .merge(source$)
    .scan((regData, modFn) => modFn(regData))//combine existing data with new one
    .shareReplay(1)
}

export default partReg<|endoftext|>


<commit_before>/*
Flow Package: core
*/
!function (window, Object, Math, Flow, undefined) {

  // init vars
  var core = Flow.pkg('core'), // define core package
    typeOf = function (obj) { // custom typeOf function
      // init vars
      var type = typeof obj; // get native type string
      // return string, check for array when an object
      return type === 'object' && Object.prototype.toString.call(obj) === '[object Array]' ? 'array' : type;
    },
    traversalNames = '_on|_in|_out|_over|_bover'.split('|'); // get traversal fnc names

  // initialize the package instance with custom properties
  core.init = function () {
    // init vars
    var pkg = this; // alias self
    // add arguments
    pkg.args = [];
    // init locked flag
    pkg.locked = 0;
    // init index of state paths
    pkg.stateIds = {};
    // init child-parent flow trackers
    pkg.childFlows = [];
    pkg.parentFlows = [];
    pkg.states.forEach(function (state, idx) {
      // index this path with this index position
      pkg.stateIds[state.location] = idx;
      // define array to hold traversal functions
      state.fncs = [];
      // define map function - curried call to target method
      state.map = function () {
        pkg.proxy.pkgs.core.target(idx, arguments);
      };
      // if this state's index is not 0...
      if (state.index) {
        // append to parent's map function
        pkg.states[state.parentIndex].map[state.name] = state.map;
      }
      // set custom toString for passing proxy reference
      state.map.toString = function () {
        // return this state's location
        return state.location;
      };
      // with each traversal name...
      traversalNames.forEach(function (name, idx) {
        //  set traversal function to 0 or the corresponding data key (when a function)
        state.fncs[idx] = typeof state.data[name] === 'function' ? state.data[name] : 0;
      });
      // if there is no _on[0] function and this state's value is a function...
      if (!state.fncs[0] && typeof state.value === 'function') {
        // use as the _on[0] traversal function
        state.fncs[0] = state.value;
      }
    });
    // set map to root map
    pkg.map = pkg.states[1].map;
  };

  // add static variables - could be private - doesn't matter
  core.activeFlows = [];

  // customize data parsing
  core.dataKey = /^_/; // pattern for identifying data keys
  core.invalidKey = /^toString$|^[\d@\[]|\/|\|/; // pattern for identifying invalid keys

  // hook into events
  core.onStart = function () {
    console.log('starting loop towards ', this.flow.targetIndex);
  };
  core.onStop = function () {
    console.log('stopping loop at ', this.flow.currentIndex);
  };
  core.onFinish = function () {
    console.log('finishing loop', this.flow.currentIndex);
  };

  // executes when a state is traversed - scope is the package instance
  core.onTraverse = function (moveInt) {
    // init vars
    var pkg = this, // the package instance
      state = pkg.states[pkg.flow.currentIndex], // the state being traversed (prototyped, read-only value)
      data = state.data; // data from the current state (shared amongst all package instances)
    // toggle internal flag (trust all calls)
    pkg.internal = 1;
    // if there is a function for this motion...
    if (state.fncs[moveInt]) {
      // execute function, in scope of the proxy - pass arguments when traversing _on[0]
      pkg.rtrn = states.fncs[moveInt].apply(pkg.proxy, moveInt ? [] : pkg.args);
    }
    // toggle internal flag (don't trust all calls)
    pkg.internal = 0;
  };

  // define prototype of any package instances
  core.prototype = {

  };

  // add method to return map of this flow's states
  core.api.map = function () {
    // return map function
    return core(this).map;
  };

  // add method to
  core.api.query = function () {
    // init vars
  	var pkg = core(this), // get package instance
  		args = arguments, // alias arguments
  		i = 0, node, // loop vars
  		nodes = []; //
  	for (; node = pkg.findNode(args[i]); i++) {
  		nodes.push(node.id);
  	}
  	// return the node id or false
  	return (nodes.length && nodes.length === args.length) ? (nodes.length > 1 ? nodes : nodes[0]) : !1;
  };

  // add method to lock and unlock
  core.api.lock = function () {
    // return map function
    return core(this).map;
  };

  // add method to manage variables
  core.api.vars = function (a1, a2) {
    // init vars
		var pkg = core(this), // get package
			args = arguments, // alias arguments
			v = typeof a1 === 'string' && sys.rxp.oneAlpha.test(a1) && flow.resolveVar(a1),
			i, rtn = !1; //
		switch (args.length) {
			case 0: // get names of all vars
				rtn = [];
				for (i in flow.vars) {
					if (flow.vars.hasOwnProperty(i)) rtn.push(i);
				}
			break;

			case 1: // get the value of this var
				if (v) rtn = v.values[0];
			break;

			default:
				// if the var is valid...
				if (v) {
					// set the current value
					v.values[0] = a2;
					rtn = !0;
				}
			break;
		}
		// return result
		return rtn;
  };

  // add method to access and edit arguments
  core.api.args = function (a1, a2) {
    // init vars
    var pkg = core(this), // retrieve package-sandbox for this proxy
      args = [].slice.call(arguments), // capture arguments as an array
      a1Ok = a1 > -1 && Math.ceil(a1) === a1; // flag when the first argument is a valid number
    // based on the number of arguments...
    switch (args.length) {
      // with zero arguments...
      case 0 :
        // return copy of arguments
        return pkg.args.concat();
      break;

      // with one argument...
      case 1:
        // based on the type of the first argument...
        switch (typeOf(a1)) {
          // when the first argument is an array...
          case 'array':
            // replace package arguments
            pkg.args = a1.concat();
            // flag success
            return true;
          break;

          // if the first argument is a number...
          case 'number':
            // if the number is valid...
            if (a1Ok) {
              // return the argument at the given index
              return pkg.args[a1];
            }
          break;
        }
      break;

      // with more than one argument...
      default:
        // if the index is valid...
        if (a1Ok) {
          // and, if the value is undefined for the last item...
          if (a2 === undefined && a1 === pkg.args.length - 1) {
            // remove last item
            pkg.args.splice(-1, 1);
          } else { // otherwise, when not a "delete" flag...
            // set value at the given index
            pkg.args[a1] = a2;
          }
          // flag success with removing or setting the value
          return !0;
        }
      break;
    }
    // (ultimately) return false
    return !1;
  };

  // add method to program api
  core.api.target = function (idx) {
    /*
      Scope ("this") is the public Flow proxy.
      The sandboxed package-instance is retrieved by passing the proxy to the package definition function.
    */
    // init vars
    var pkg = core(this); // get the package instance related to this flow proxy
                          // could also be done as:
                          // > var pkg = Flow.pkg('core')(this);
    // if the target index is valid...
    if (idx < pkg.states.length) {
      // capture arguments after idx
      pkg.arguments = [].slice.call(arguments).slice(1);
      // pkg.flow provides control and access to the true flow instance
      pkg.flow.go(idx); // tell flow to go here
    }
  };

  // add method to resume
  core.api.go = function () {
  };

  // delay traversing
  core.api.wait = function () {
    // init vars
		var pkg = core(this), // get package instance
			args = arguments, // alias arguments
			cur = pkg.states[pkg.flow.currentIndex], //
			cache = pkg.cache.proxy, //
			argLn = args.length, //
			M = Math, // reduce lookups
			fnc = argLn > 1 ? args[0] : 0, //
			node, // stub to test when fnc is a node reference
			fncOk = !fnc || typeof fnc === 'function' || ((node = pkg.flow.findNode(fnc)) && cur.allowTgt(node)), //
			time = Math.ceil(Math.abs(args[argLn - 1])), //
			timeOk = !isNaN(time), //
			rtn = 1; //
		// if there are targets or staged waypoints to reach, and the argument's are valid (node is not false)...
		if ((flow.targets.length || flow.stage.waypoints.length) && (!argLn || (timeOk && fncOk && node !== !1))) {
			// if reset traversal cache
			if (cache.status) {
			  //
				delete cache.status.traversal;
			}
			// clear existing delay
			flow.clearDelay();
			// if fnc was a node, make a function that targets it, as the callback
			if (node) {
			  // define callback function
			  fnc = function () {
			    //
			    flow.target(node);
			  };
		  }
			// set delay to truthy value or delayed traverse call
			pkg.delay.active = argLn ? window.setTimeout(function () {
					// set callback next callback
					pkg.delay.callback = fnc;
					// clear delay
					pkg.delay.active = 0;
					// attempt traversal - invokes callback
					pkg.traverse();
				}, time) : 1;
			// flag that the flow will be (or has been) delayed
			rtn = 0;
		}
		// return boolean flag of success or failure
		return !rtn;
  };
}(this, Object, Math, Flow);<commit_msg>_var component working<commit_after>/*
Flow Package: core
*/
!function (window, Object, Array, Math, Flow, undefined) {

  // init vars
  var core = Flow.pkg('core'), // define core package
    typeOf = function (obj) { // custom typeOf function
      // init vars
      var type = typeof obj; // get native type string
      // return string, check for array when an object
      return type === 'object' && ~((new Object()).toString.call(obj).indexOf('y')) ? 'array' : type;
    },
    rxps = [ // collection of regular expressions
      /\w/ // 0 - one alpha numeric character
    ],
    /*
    this generator handles any nesting and combination of _var component values...
    ...strings
      > _var: 'foo'
    ...objects
      > _var: {foo: 'bar'}
    ...arrays of strings, arrays and objects
      > _var: ['f', 'o', 'b']
      > _var: [['f'], ['o'], ['b]]
      > _var: [{foo: 'bar'}, {hello: 'world'}]
      > _var: [['g',{foo: 'bar'}], 'alpha', {accts: 9}] // mixed
    */
    genVars = new genData(function (name, value, parent, dataset, flags) { // generator to extract variable pairs from a _var component
      // init vars
      var data = this; // alias self
      // flag when this is an object
      data.O = typeof value === 'object';
      // flag when this is an Array
      data.A = value instanceof Array;
      // flag that this has a value (true by default)
      data.V = 1;
      // if there is a parent...
      if (parent) {
        // if the parent is an array...
        if (parent.A) {
          // if this is an object...
          if (data.O) {
            // exclude from result when this is an object within an array
            flags.exclude = 1;
          }
        } else { // otherwise, when the parent is not an array (assume the parent is an object)...
          // don't scan the children of this object (because it's the value, not a _var config)
          flags.scanValue = 0;
        }
      } else if (data.O) { // otherwise, when the first item is an object...
        // exclude from the result
        flags.exclude = 1;
      }
      // if this data has not been exluced...
      if (!flags.exclude) {
        // if there is no parent, or the parent is an array...
        if (!parent || parent.A) {
          // use the value as the name
          data.name = value;
          // set the value to undefined
          data.value = undefined;
          // flag that this data has no value
          data.V = 0;
        }
        // if the name is invalid...
        if (data.name == null || !/\w/.test(data.name)) {
          // exclude this data
          flags.exclude = 1;
        }
        // if this data is still not excluded...
        if (!flags.exclude) {
          // find and remove any data with the same name
          dataset
            .filter(function (d, i) {
              // get the (one) item with the same name
              return d.name === data.name && ((d.I = i) || 1);
            })
            .forEach(function (d) {
              // remove the duplicate index (only ever one)
              dataset.splice(d.I,1);
            });
        }
      }
    }),
    activeFlows = [], // collection of active flows
    Variable = function (flow, key) {
      var v = this;
      v.flow = flow;
      v.key = key;
      v.values = [undefined]; // initial value is undefined
      // add self to flow's vars
      flow.vars[key] = v;
    };
	Variable.prototype = {
		descope: function () {
			var v = this;
			// remove scope from values
			v.values.shift();
			// if no more scope levels exist, remove self-reference from flow
			if (!v.values.length) delete v.flow.vars[v.key];
			// flag that this instance was descoped
			return 1;
		},
		scope: function () {
			var v = this;
			// copy current value as the new value (first value)
			v.values.unshift(v.values[0]);
			// flag that this instance was scoped
			return 1;
		}
	};

  // define traversal event names
  core.events = 'main|in|out|over'.split('|');

  // customize data parsing
  core.dataKey = /^_/; // pattern for identifying data keys
  core.invalidKey = /^toString$|^[@\[]|[\/\|]/; // pattern for identifying invalid keys

  // initialize the package instance with custom properties
  core.init = function () {
    // init vars
    var pkg = this; // alias self
    // add arguments
    pkg.args = [];
    // collection of variables
    pkg.vars = {};
    // init locked flag
    pkg.locked = 0;
    // init index of state paths
    pkg.stateIds = {};
    // init child-parent flow trackers
    pkg.childFlows = [];
    pkg.parentFlows = [];
    // collection of targets
    pkg.targets = [];
    // initialize each state
    pkg.states.forEach(function (state, idx) {
      // init vars
      var parent = idx && pkg.states[state.parentIndex]; // capture parent when available
      // index this path with this index position
      pkg.stateIds[state.location] = idx;
      // define array to hold traversal functions
      state.fncs = [];
      // set pendable flag
      state.pendable = parent ? parent.pendable : 0;
      // set isRoot flag, based on index or "_root" component
      state.isRoot = idx < 2 ? 1 : !!state.data._root;
      // set restricted path to this state's location, based on the presence of the "_restrict" component or the parent's restrict path
      state.restrictPath = state.data._restrict ? state.location : (parent ? parent.restrictPath : '');
      // define map function - a curried call to .target()
      state.map = function () {
        // invoke target explicitly
        return pkg.proxy.pkgs.core.target(idx, arguments);
      };
      // add variable configurations for this node
      state.vars = genVars(state.data._vars).map(function (data) {
        // return an object based on the given flags
        return {
          name: data.name, // variable name
          value: data.value, // variable value
          use: data.V // flag indicating whether this value should be used when this variable is scoped
        };
      });
      // if this state's index is not 0...
      if (state.index) {
        // append to parent's map function
        parent.map[state.name] = state.map;
      }
      // set custom toString for passing proxy reference
      state.map.toString = function () {
        // return this state's location
        return state.location;
      };
      // with each traversal name...
      core.events.forEach(function (name, idx) {
        name = '_' + name;
        //  set traversal function to 0 or the corresponding data key (when a function)
        state.fncs[idx] = typeof state.data[name] === 'function' ? state.data[name] : 0;
      });
      // if there is no _on[0] function and this state's value is a function...
      if (!state.fncs[0] && typeof state.value === 'function') {
        // use as the _on[0] traversal function
        state.fncs[0] = state.value;
      }
    });
  };

  // hook into events
  core.onStart = function () {
    // init vars
    var pkg = this; // alias this package
    // activate this flow
    //pkg.activate();
  };
  core.onStop = function () {
    // init vars
    var pkg = this; // alias this package
    // remove self from active flows
    //activeFlows.unshift();
  };
  core.onFinish = function () {
    /*
    // init vars
    var pkg = this, // alias self
      tgts = pkg.targets; // alias targets
    // remove the last target...
    tgts.pop();
    // if there are more targets...
    if (tgts.length) {
      // go to the next target
      pkg.flow.go(tgts[tgts.length - 1]);
    } else { // otherwise, when there are no more targets...
      // clear cache?
      // clear history?
      // remove from activeFlows
      activeFlows.pop();
      // inform parent flows
    }*/
  };

  // executes when a state is traversed - scope is the package instance
  core.onTraverse = function (moveInt) {
    // init vars
    var pkg = this, // the package instance
      state = pkg.states[pkg.flow.currentIndex]; // the state being traversed (prototyped, read-only value)
    // toggle internal flag (trust all calls)
    pkg.trust = 1;
    // if there is an out state...
    if (pkg.outState) {
      console.log('de-scoping', pkg.outState.name, '\n\tvCfgs:', pkg.outState.vars);
      // descope variables in the outstate
      pkg.scopeVars(pkg.outState, 1);
      // clear the outstate
      pkg.outState = 0;
    }
    // based on the motion...
    switch (moveInt) {
      case 1: // in
        console.log('scoping', state.name, '\n\tvCfgs:', state.vars);
        // scope variables for this state
        pkg.scopeVars(state);
      break;

      case 2: // out
        // set the outState to the current state
        pkg.outState = state;
      break;
    }
    // if there is a function for this motion...
    if (state.fncs[moveInt]) {
      // execute function, in scope of the proxy - pass arguments when traversing _on[0]
      pkg.rtrn = state.fncs[moveInt].apply(pkg.proxy, moveInt ? [] : pkg.args);
    }
    // toggle internal flag (don't trust all calls)
    pkg.trust = 0;
  };

  // define prototype of any package instances
  core.prototype = {
    activate: function () {
      // if there is an active flow...
      if (activeFlows.length) {
        // add this flow as a child of the active flow
        activeFlows[0].childFlows.push(pkg);
        // add the active flow as a parent of this flow
        pkg.parentFlows.push(pkg);
      }
      // add self to activeFlows
      activeFlows.shift(pkg);
    },
    deactivate: function () {
    },
    // add a variable-tracking-object to this package
    getVar: function (name) {
      // init vars
      var pkg = this; // alias self
      // return an existing or new variable tracking object
      return (pkg.vars.hasOwnProperty(name)) ? pkg.vars[name] : (pkg.vars[name] = {
        name: name,
        values: []
      });
    },
    // create/remove variable tracking objects and increase/reduce their values
    scopeVars: function (state, descope) {
      // init vars
      var pkg = this; // alias self (for closure)
      // with each variable in the given state
      state.vars.forEach(function (varCfg) {
        // init vars
        var vto = pkg.getVar(varCfg.name); // the variable tracking object with this name
        // if descoping variables...
        if (descope) {
          // remove current value from values
          vto.values.shift();
          // if no other values exist...
          if (!vto.values.length) {
            // remove the variable tracking object
            delete pkg.vars[varCfg.name];
          }
        } else { // otherwise, when scoping a variable tracking object...
          // add new or copied value, based on the config
          vto.values.unshift(varCfg.use ? varCfg.value : vto.values[0]);
        }
      });
    }
  };

  // add method to return map of this flow's states
  core.api.map = function () {
    // return pre-made function-list - from the root state
    return core(this).states[1].map;
  };

  // add method to
  core.api.query = function () {
    // init vars
  	var pkg = core(this), // get package instance
  		args = arguments, // alias arguments
  		i = 0, node, // loop vars
  		nodes = []; //
  	for (; node = pkg.findNode(args[i]); i++) {
  		nodes.push(node.id);
  	}
  	// return the node id or false
  	return (nodes.length && nodes.length === args.length) ? (nodes.length > 1 ? nodes : nodes[0]) : !1;
  };

  // add method to lock and unlock
  core.api.lock = function () {
  };

  // add method to manage variables
  core.api.vars = function (a1, a2) {
    // init vars
		var pkg = core(this), // get package
			args = arguments, // alias arguments
			v = typeof a1 === 'string' && /\w/.test(a1) && flow.resolveVar(a1),
			i, rtn = !1; //
		switch (args.length) {
			case 0: // get names of all vars
				rtn = [];
				for (i in flow.vars) {
					if (flow.vars.hasOwnProperty(i)) rtn.push(i);
				}
			break;

			case 1: // get the value of this var
				if (v) rtn = v.values[0];
			break;

			default:
				// if the var is valid...
				if (v) {
					// set the current value
					v.values[0] = a2;
					rtn = !0;
				}
			break;
		}
		// return result
		return rtn;
  };

  // add method to access and edit arguments
  core.api.args = function (a1, a2) {
    // init vars
    var pkg = core(this), // retrieve package-sandbox for this proxy
      args = [].slice.call(arguments), // capture arguments as an array
      a1Ok = a1 > -1 && Math.ceil(a1) === a1; // flag when the first argument is a valid number
    // based on the number of arguments...
    switch (args.length) {
      // with zero arguments...
      case 0 :
        // return copy of arguments
        return pkg.args.concat();
      break;

      // with one argument...
      case 1:
        // based on the type of the first argument...
        switch (typeOf(a1)) {
          // when the first argument is an array...
          case 'array':
            // replace package arguments
            pkg.args = a1.concat();
            // flag success
            return true;
          break;

          // if the first argument is a number...
          case 'number':
            // if the number is valid...
            if (a1Ok) {
              // return the argument at the given index
              return pkg.args[a1];
            }
          break;
        }
      break;

      // with more than one argument...
      default:
        // if the index is valid...
        if (a1Ok) {
          // and, if the value is undefined for the last item...
          if (a2 === undefined && a1 === pkg.args.length - 1) {
            // remove last item
            pkg.args.splice(-1, 1);
          } else { // otherwise, when not a "delete" flag...
            // set value at the given index
            pkg.args[a1] = a2;
          }
          // flag success with removing or setting the value
          return !0;
        }
      break;
    }
    // (ultimately) return false
    return !1;
  };

  // add method to program api
  core.api.target = function (idx) {
    /*
      Scope ("this") is the public Flow proxy.
      The sandboxed package-instance is retrieved by passing the proxy to the package definition function.
    */
    // init vars
    var pkg = core(this); // get the package instance related to this flow proxy
                          // could also be done as:
                          // > var pkg = Flow.pkg('core')(this);
    // if the target index is valid...
    if (idx < pkg.states.length) {
      // capture arguments after idx
      pkg.arguments = [].slice.call(arguments).slice(1);
      // pkg.flow provides control and access to the true flow instance
      pkg.flow.go(idx); // tell flow to go here
    }
  };

  // add method to resume
  core.api.go = function () {
  };

  // delay traversing
  core.api.wait = function () {
    // init vars
		var pkg = core(this), // get package instance
			args = arguments, // alias arguments
			cur = pkg.states[pkg.flow.currentIndex], //
			cache = pkg.cache.proxy, //
			argLn = args.length, //
			fnc = argLn > 1 ? args[0] : 0, //
			node, // stub to test when fnc is a node reference
			fncOk = !fnc || typeof fnc === 'function' || ((node = pkg.flow.findNode(fnc)) && cur.allowTgt(node)), //
			time = Math.ceil(Math.abs(args[argLn - 1])), //
			timeOk = !isNaN(time), //
			rtn = 1; //
		// if there are targets or staged waypoints to reach, and the argument's are valid (node is not false)...
		if ((flow.targets.length || flow.stage.waypoints.length) && (!argLn || (timeOk && fncOk && node !== !1))) {
			// if reset traversal cache
			if (cache.status) {
			  //
				delete cache.status.traversal;
			}
			// clear existing delay
			flow.clearDelay();
			// if fnc was a node, make a function that targets it, as the callback
			if (node) {
			  // define callback function
			  fnc = function () {
			    //
			    flow.target(node);
			  };
		  }
			// set delay to truthy value or delayed traverse call
			pkg.delay.active = argLn ? window.setTimeout(function () {
					// set callback next callback
					pkg.delay.callback = fnc;
					// clear delay
					pkg.delay.active = 0;
					// attempt traversal - invokes callback
					pkg.traverse();
				}, time) : 1;
			// flag that the flow will be (or has been) delayed
			rtn = 0;
		}
		// return boolean flag of success or failure
		return !rtn;
  };
}(this, Object, Array, Math, Flow);<|endoftext|>