<commit_before>/**
 * @file Require javascript resource handling
 * @since 0.2.2
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_HOST*/ // Host types
/*global _gpfArraySlice*/ // [].slice.call
/*global _gpfErrorDeclare*/ // Declare new gpf.Error names
/*global _gpfFunc*/ // Create a new function using the source
/*global _gpfHost*/ // Host type
/*global _gpfIgnore*/ // Helper to remove unused parameter warning
/*global _gpfPathJoin*/ // Join all arguments together and normalize the resulting path
/*global _gpfPathParent*/ // Get the parent of a path
/*global _gpfRegExpForEach*/ // Executes the callback for each match of the regular expression
/*global _gpfRequireProcessor*/ // Mapping of resource extension to processor function
/*global _gpfRequireWrapGpf*/ // Wrap gpf to fit the new context and give access to gpf.require.define promise
/*#endif*/

_gpfErrorDeclare("require/javascript", {

    /**
     * ### Summary
     *
     * Dynamic require not supported
     *
     * ### Description
     *
     * When loading a [CommonJS](http://www.commonjs.org/) module, a first pass is done to extract all requires being
     * called. If the require is based on a complex parameter (variable or string manipulation), the loader won't be
     * able to understand the require. No fallback mechanism is implemented yet
     * @since 0.2.2
     */
    noCommonJSDynamicRequire:
        "Dynamic require not supported"

});

var _gpfRequireJsModuleRegEx = /[^.]\brequire\b\s*\(\s*(?:['|"]([^"']+)['|"]|[^)]+)\s*\)/g;

function _gpfRequireJSGetStaticDependencies (resourceName, content) {
    /*jshint validthis:true*/
    var requires = _gpfRegExpForEach(_gpfRequireJsModuleRegEx, content);
    if (requires.length) {
        return _gpfRequireWrapGpf(this, resourceName).gpf.require.define(requires //eslint-disable-line no-invalid-this
            .map(function (match) {
                return match[1]; // may be undefined if dynamic
            })
            .filter(function (require) {
                return require;
            })
            .reduce(function (dictionary, name) {
                dictionary[name] = name;
                return dictionary;
            }, {}),
        function (require) {
            return require;
        });
    }
    return Promise.resolve({}); // No static dependencies
}

//region AMD define wrapper

function _gpfRequireAmdDefineParamsFactoryOnly (factory) {
    return {
        dependencies: [],
        factory: factory
    };
}

function _gpfRequireAmdDefineParamsDependenciesAndFactory (dependencies, factory) {
    return {
        dependencies: dependencies,
        factory: factory
    };
}

function _gpfRequireAmdDefineParamsAll (any, dependencies, factory) {
    return {
        dependencies: dependencies,
        factory: factory
    };
}

var
    /**
     * Mapping of define parameter count to dependencies / factory
     *
     * @type {Function[]}
     * @since 0.2.2
     */
    _gpfRequireAmdDefineParamsMapping = [
        null,
        _gpfRequireAmdDefineParamsFactoryOnly,
        _gpfRequireAmdDefineParamsDependenciesAndFactory,
        _gpfRequireAmdDefineParamsAll
    ];

function _gpfRequireAmdDefine (name, dependencies, factory) {
    /*jshint validthis:true*/
    _gpfIgnore(name, dependencies, factory);
    var myGpf = this, //eslint-disable-line
        params = _gpfRequireAmdDefineParamsMapping[arguments.length].apply(null, arguments);
    myGpf.require.define(params.dependencies, function (require) {
        require.length = params.dependencies.length;
        return params.factory.apply(null, _gpfArraySlice(require));
    });
}

function _gpfRequireJS (myGpf, content, staticDependencies) {
    var module = {};
    _gpfFunc(["gpf", "define", "module", "require"], content)(
        myGpf,
        _gpfRequireAmdDefine.bind(myGpf),
        module,
        function (name) {
            return staticDependencies[name] || gpf.Error.noCommonJSDynamicRequire();
        }
    );
    return module.exports;
}

/*global location*/

function _gpfRequireSourceMapBrowswer (name, content) {
    var parentPath = location.pathname.toString();
    /* istanbul ignore else */ // sourceURL.1
    if (!parentPath.endsWith("/")) {
        parentPath = _gpfPathParent(parentPath);
    }
    return "//# sourceURL=" + location.origin + _gpfPathJoin(parentPath, name) + "?gpf.require\n" + content;
}

function _gpfRequireSourceMapNone (name, content) {
    return content;
}

var _gpfRequireSourceMapImpl;
if (_GPF_HOST.BROWSER === _gpfHost) {
    _gpfRequireSourceMapImpl = _gpfRequireSourceMapBrowswer;

} else {
    _gpfRequireSourceMapImpl = _gpfRequireSourceMapNone;

}

_gpfRequireProcessor[".js"] = function (resourceName, content) {
    var wrapper = _gpfRequireWrapGpf(this, resourceName);
    return _gpfRequireJSGetStaticDependencies.call(this, resourceName, content)
        .then(function (staticDependencies) {
            var exports = _gpfRequireJS(wrapper.gpf, _gpfRequireSourceMapImpl(resourceName, content),
                staticDependencies);
            if (undefined === exports) {
                return wrapper.promise;
            }
            return exports;
        });
};
<commit_msg>no-magic-numbers (#280)<commit_after>/**
 * @file Require javascript resource handling
 * @since 0.2.2
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_HOST*/ // Host types
/*global _gpfArraySlice*/ // [].slice.call
/*global _gpfErrorDeclare*/ // Declare new gpf.Error names
/*global _gpfFunc*/ // Create a new function using the source
/*global _gpfHost*/ // Host type
/*global _gpfIgnore*/ // Helper to remove unused parameter warning
/*global _gpfPathJoin*/ // Join all arguments together and normalize the resulting path
/*global _gpfPathParent*/ // Get the parent of a path
/*global _gpfRegExpForEach*/ // Executes the callback for each match of the regular expression
/*global _gpfRequireProcessor*/ // Mapping of resource extension to processor function
/*global _gpfRequireWrapGpf*/ // Wrap gpf to fit the new context and give access to gpf.require.define promise
/*#endif*/

_gpfErrorDeclare("require/javascript", {

    /**
     * ### Summary
     *
     * Dynamic require not supported
     *
     * ### Description
     *
     * When loading a [CommonJS](http://www.commonjs.org/) module, a first pass is done to extract all requires being
     * called. If the require is based on a complex parameter (variable or string manipulation), the loader won't be
     * able to understand the require. No fallback mechanism is implemented yet
     * @since 0.2.2
     */
    noCommonJSDynamicRequire:
        "Dynamic require not supported"

});

var _gpfRequireJsModuleRegEx = /[^.]\brequire\b\s*\(\s*(?:['|"]([^"']+)['|"]|[^)]+)\s*\)/g,
    _GPF_REQUIRE_MATCH_MODULE_NAME = 1;

function _gpfRequireJSGetStaticDependencies (resourceName, content) {
    /*jshint validthis:true*/
    var requires = _gpfRegExpForEach(_gpfRequireJsModuleRegEx, content);
    if (requires.length) {
        return _gpfRequireWrapGpf(this, resourceName).gpf.require.define(requires //eslint-disable-line no-invalid-this
            .map(function (match) {
                return match[_GPF_REQUIRE_MATCH_MODULE_NAME]; // may be undefined if dynamic
            })
            .filter(function (require) {
                return require;
            })
            .reduce(function (dictionary, name) {
                dictionary[name] = name;
                return dictionary;
            }, {}),
        function (require) {
            return require;
        });
    }
    return Promise.resolve({}); // No static dependencies
}

//region AMD define wrapper

function _gpfRequireAmdDefineParamsFactoryOnly (factory) {
    return {
        dependencies: [],
        factory: factory
    };
}

function _gpfRequireAmdDefineParamsDependenciesAndFactory (dependencies, factory) {
    return {
        dependencies: dependencies,
        factory: factory
    };
}

function _gpfRequireAmdDefineParamsAll (any, dependencies, factory) {
    return {
        dependencies: dependencies,
        factory: factory
    };
}

var
    /**
     * Mapping of define parameter count to dependencies / factory
     *
     * @type {Function[]}
     * @since 0.2.2
     */
    _gpfRequireAmdDefineParamsMapping = [
        null,
        _gpfRequireAmdDefineParamsFactoryOnly,
        _gpfRequireAmdDefineParamsDependenciesAndFactory,
        _gpfRequireAmdDefineParamsAll
    ];

function _gpfRequireAmdDefine (name, dependencies, factory) {
    /*jshint validthis:true*/
    _gpfIgnore(name, dependencies, factory);
    var myGpf = this, //eslint-disable-line
        params = _gpfRequireAmdDefineParamsMapping[arguments.length].apply(null, arguments);
    myGpf.require.define(params.dependencies, function (require) {
        require.length = params.dependencies.length;
        return params.factory.apply(null, _gpfArraySlice(require));
    });
}

function _gpfRequireJS (myGpf, content, staticDependencies) {
    var module = {};
    _gpfFunc(["gpf", "define", "module", "require"], content)(
        myGpf,
        _gpfRequireAmdDefine.bind(myGpf),
        module,
        function (name) {
            return staticDependencies[name] || gpf.Error.noCommonJSDynamicRequire();
        }
    );
    return module.exports;
}

/*global location*/

function _gpfRequireSourceMapBrowswer (name, content) {
    var parentPath = location.pathname.toString();
    /* istanbul ignore else */ // sourceURL.1
    if (!parentPath.endsWith("/")) {
        parentPath = _gpfPathParent(parentPath);
    }
    return "//# sourceURL=" + location.origin + _gpfPathJoin(parentPath, name) + "?gpf.require\n" + content;
}

function _gpfRequireSourceMapNone (name, content) {
    return content;
}

var _gpfRequireSourceMapImpl;
if (_GPF_HOST.BROWSER === _gpfHost) {
    _gpfRequireSourceMapImpl = _gpfRequireSourceMapBrowswer;

} else {
    _gpfRequireSourceMapImpl = _gpfRequireSourceMapNone;

}

_gpfRequireProcessor[".js"] = function (resourceName, content) {
    var wrapper = _gpfRequireWrapGpf(this, resourceName);
    return _gpfRequireJSGetStaticDependencies.call(this, resourceName, content)
        .then(function (staticDependencies) {
            var exports = _gpfRequireJS(wrapper.gpf, _gpfRequireSourceMapImpl(resourceName, content),
                staticDependencies);
            if (undefined === exports) {
                return wrapper.promise;
            }
            return exports;
        });
};
<|endoftext|>


<commit_before>/*
Language: C#
Author: Jason Diamond <jason@diamond.name>
Contributor: Nicolas LLOBERA <nllobera@gmail.com>
Category: common
*/

function(hljs) {
  var KEYWORDS = {
    keyword:
      // Normal keywords.
      'abstract as base bool break byte case catch char checked const continue decimal ' +
      'default delegate do double else enum event explicit extern finally fixed float ' +
      'for foreach goto if implicit in int interface internal is lock long nameof ' +
      'object operator out override params private protected public readonly ref sbyte ' +
      'sealed short sizeof stackalloc static string struct switch this try typeof ' +
      'uint ulong unchecked unsafe ushort using virtual void volatile while ' +
      // Contextual keywords.
      'add alias ascending async await by descending dynamic equals from get global group into join ' +
      'let on orderby partial remove select set value var where yield',
    literal:
      'null false true'
  };

  var VERBATIM_STRING = {
    className: 'string',
    begin: '@"', end: '"',
    contains: [{begin: '""'}]
  };
  var VERBATIM_STRING_NO_LF = hljs.inherit(VERBATIM_STRING, {illegal: /\n/});
  var SUBST = {
    className: 'subst',
    begin: '{', end: '}',
    keywords: KEYWORDS
  };
  var SUBST_NO_LF = hljs.inherit(SUBST, {illegal: /\n/});
  var INTERPOLATED_STRING = {
    className: 'string',
    begin: /\$"/, end: '"',
    illegal: /\n/,
    contains: [{begin: '{{'}, {begin: '}}'}, hljs.BACKSLASH_ESCAPE, SUBST_NO_LF]
  };
  var INTERPOLATED_VERBATIM_STRING = {
    className: 'string',
    begin: /\$@"/, end: '"',
    contains: [{begin: '{{'}, {begin: '}}'}, {begin: '""'}, SUBST]
  };
  var INTERPOLATED_VERBATIM_STRING_NO_LF = hljs.inherit(INTERPOLATED_VERBATIM_STRING, {
    illegal: /\n/,
    contains: [{begin: '{{'}, {begin: '}}'}, {begin: '""'}, SUBST_NO_LF]
  });
  SUBST.contains = [
    INTERPOLATED_VERBATIM_STRING,
    INTERPOLATED_STRING,
    VERBATIM_STRING,
    hljs.APOS_STRING_MODE,
    hljs.QUOTE_STRING_MODE,
    hljs.C_NUMBER_MODE,
    hljs.C_BLOCK_COMMENT_MODE
  ];
  SUBST_NO_LF.contains = [
    INTERPOLATED_VERBATIM_STRING_NO_LF,
    INTERPOLATED_STRING,
    VERBATIM_STRING_NO_LF,
    hljs.APOS_STRING_MODE,
    hljs.QUOTE_STRING_MODE,
    hljs.C_NUMBER_MODE,
    hljs.inherit(hljs.C_BLOCK_COMMENT_MODE, {illegal: /\n/})
  ];
  var STRING = {
    variants: [
      INTERPOLATED_VERBATIM_STRING,
      INTERPOLATED_STRING,
      VERBATIM_STRING,
      hljs.APOS_STRING_MODE,
      hljs.QUOTE_STRING_MODE
    ]
  };

  var TYPE_IDENT_RE = hljs.IDENT_RE + '(<' + hljs.IDENT_RE + '(\\s*,\\s*' + hljs.IDENT_RE + ')*>)?(\\[\\])?';

  return {
    aliases: ['csharp'],
    keywords: KEYWORDS,
    illegal: /::/,
    contains: [
      hljs.COMMENT(
        '///',
        '$',
        {
          returnBegin: true,
          contains: [
            {
              className: 'doctag',
              variants: [
                {
                  begin: '///', relevance: 0
                },
                {
                  begin: '<!--|-->'
                },
                {
                  begin: '</?', end: '>'
                }
              ]
            }
          ]
        }
      ),
      hljs.C_LINE_COMMENT_MODE,
      hljs.C_BLOCK_COMMENT_MODE,
      {
        className: 'meta',
        begin: '#', end: '$',
        keywords: {
          'meta-keyword': 'if else elif endif define undef warning error line region endregion pragma checksum'
        }
      },
      STRING,
      hljs.C_NUMBER_MODE,
      {
        beginKeywords: 'class interface', end: /[{;=]/,
        illegal: /[^\s:]/,
        contains: [
          hljs.TITLE_MODE,
          hljs.C_LINE_COMMENT_MODE,
          hljs.C_BLOCK_COMMENT_MODE
        ]
      },
      {
        beginKeywords: 'namespace', end: /[{;=]/,
        illegal: /[^\s:]/,
        contains: [
          hljs.inherit(hljs.TITLE_MODE, {begin: '[a-zA-Z](\\.?\\w)*'}),
          hljs.C_LINE_COMMENT_MODE,
          hljs.C_BLOCK_COMMENT_MODE
        ]
      },
      {
        // [Attributes("")]
        className: 'title',
        begin: '^\\s*\\[', excludeBegin: true, end: '[\\(\\]]', excludeEnd: true,
        contains: [
          STRING
        ]
      },
      {
        // Expression keywords prevent 'keyword Name(...)' from being
        // recognized as a function definition
        beginKeywords: 'new return throw await',
        relevance: 0
      },
      {
        className: 'function',
        begin: '(' + TYPE_IDENT_RE + '\\s+)+' + hljs.IDENT_RE + '\\s*\\(', returnBegin: true,
        end: /[{;=]/, excludeEnd: true,
        keywords: KEYWORDS,
        contains: [
          {
            begin: hljs.IDENT_RE + '\\s*\\(', returnBegin: true,
            contains: [hljs.TITLE_MODE],
            relevance: 0
          },
          {
            className: 'params',
            begin: /\(/, end: /\)/,
            excludeBegin: true,
            excludeEnd: true,
            keywords: KEYWORDS,
            relevance: 0,
            contains: [
              STRING,
              hljs.C_NUMBER_MODE,
              hljs.C_BLOCK_COMMENT_MODE
            ]
          },
          hljs.C_LINE_COMMENT_MODE,
          hljs.C_BLOCK_COMMENT_MODE
        ]
      }
    ]
  };
}
<commit_msg><commit_after>/*
Language: C#
Author: Jason Diamond <jason@diamond.name>
Contributor: Nicolas LLOBERA <nllobera@gmail.com>
Category: common
*/

function(hljs) {
  var KEYWORDS = {
    keyword:
      // Normal keywords.
      'abstract as base bool break byte case catch char checked const continue decimal ' +
      'default delegate do double else enum event explicit extern finally fixed float ' +
      'for foreach goto if implicit in int interface internal is lock long nameof ' +
      'object operator out override params private protected public readonly ref sbyte ' +
      'sealed short sizeof stackalloc static string struct switch this try typeof ' +
      'uint ulong unchecked unsafe ushort using virtual void volatile while ' +
      // Contextual keywords.
      'add alias ascending async await by descending dynamic equals from get global group into join ' +
      'let on orderby partial remove select set value var where yield',
    literal:
      'null false true'
  };

  var VERBATIM_STRING = {
    className: 'string',
    begin: '@"', end: '"',
    contains: [{begin: '""'}]
  };
  var VERBATIM_STRING_NO_LF = hljs.inherit(VERBATIM_STRING, {illegal: /\n/});
  var SUBST = {
    className: 'subst',
    begin: '{', end: '}',
    keywords: KEYWORDS
  };
  var SUBST_NO_LF = hljs.inherit(SUBST, {illegal: /\n/});
  var INTERPOLATED_STRING = {
    className: 'string',
    begin: /\$"/, end: '"',
    illegal: /\n/,
    contains: [{begin: '{{'}, {begin: '}}'}, hljs.BACKSLASH_ESCAPE, SUBST_NO_LF]
  };
  var INTERPOLATED_VERBATIM_STRING = {
    className: 'string',
    begin: /\$@"/, end: '"',
    contains: [{begin: '{{'}, {begin: '}}'}, {begin: '""'}, SUBST]
  };
  var INTERPOLATED_VERBATIM_STRING_NO_LF = hljs.inherit(INTERPOLATED_VERBATIM_STRING, {
    illegal: /\n/,
    contains: [{begin: '{{'}, {begin: '}}'}, {begin: '""'}, SUBST_NO_LF]
  });
  SUBST.contains = [
    INTERPOLATED_VERBATIM_STRING,
    INTERPOLATED_STRING,
    VERBATIM_STRING,
    hljs.APOS_STRING_MODE,
    hljs.QUOTE_STRING_MODE,
    hljs.C_NUMBER_MODE,
    hljs.C_BLOCK_COMMENT_MODE
  ];
  SUBST_NO_LF.contains = [
    INTERPOLATED_VERBATIM_STRING_NO_LF,
    INTERPOLATED_STRING,
    VERBATIM_STRING_NO_LF,
    hljs.APOS_STRING_MODE,
    hljs.QUOTE_STRING_MODE,
    hljs.C_NUMBER_MODE,
    hljs.inherit(hljs.C_BLOCK_COMMENT_MODE, {illegal: /\n/})
  ];
  var STRING = {
    variants: [
      INTERPOLATED_VERBATIM_STRING,
      INTERPOLATED_STRING,
      VERBATIM_STRING,
      hljs.APOS_STRING_MODE,
      hljs.QUOTE_STRING_MODE
    ]
  };

  var TYPE_IDENT_RE = hljs.IDENT_RE + '(<' + hljs.IDENT_RE + '(\\s*,\\s*' + hljs.IDENT_RE + ')*>)?(\\[\\])?';

  return {
    aliases: ['csharp'],
    keywords: KEYWORDS,
    illegal: /::/,
    contains: [
      hljs.COMMENT(
        '///',
        '$',
        {
          returnBegin: true,
          contains: [
            {
              className: 'doctag',
              variants: [
                {
                  begin: '///', relevance: 0
                },
                {
                  begin: '<!--|-->'
                },
                {
                  begin: '</?', end: '>'
                }
              ]
            }
          ]
        }
      ),
      hljs.C_LINE_COMMENT_MODE,
      hljs.C_BLOCK_COMMENT_MODE,
      {
        className: 'meta',
        begin: '#', end: '$',
        keywords: {
          'meta-keyword': 'if else elif endif define undef warning error line region endregion pragma checksum'
        }
      },
      STRING,
      hljs.C_NUMBER_MODE,
      {
        beginKeywords: 'class interface', end: /[{;=]/,
        illegal: /[^\s:]/,
        contains: [
          hljs.TITLE_MODE,
          hljs.C_LINE_COMMENT_MODE,
          hljs.C_BLOCK_COMMENT_MODE
        ]
      },
      {
        beginKeywords: 'namespace', end: /[{;=]/,
        illegal: /[^\s:]/,
        contains: [
          hljs.inherit(hljs.TITLE_MODE, {begin: '[a-zA-Z](\\.?\\w)*'}),
          hljs.C_LINE_COMMENT_MODE,
          hljs.C_BLOCK_COMMENT_MODE
        ]
      },
      {
        // [Attributes("")]
        className: 'title',
        begin: '^\\s*\\[', excludeBegin: true, end: '[\\(\\]]', excludeEnd: true,
        contains: [
          STRING
        ]
      },
      {
        // Expression keywords prevent 'keyword Name(...)' from being
        // recognized as a function definition
        beginKeywords: 'new return throw await',
        relevance: 0
      },
      {
        className: 'function',
        begin: '(' + TYPE_IDENT_RE + '\\s+)+[A-Z]\\w*\\s*\\(', returnBegin: true,
        end: /[{;=]/, excludeEnd: true,
        keywords: KEYWORDS,
        contains: [
          {
            begin: hljs.IDENT_RE + '\\s*\\(', returnBegin: true,
            contains: [hljs.TITLE_MODE],
            relevance: 0
          },
          {
            className: 'params',
            begin: /\(/, end: /\)/,
            excludeBegin: true,
            excludeEnd: true,
            keywords: KEYWORDS,
            relevance: 0,
            contains: [
              STRING,
              hljs.C_NUMBER_MODE,
              hljs.C_BLOCK_COMMENT_MODE
            ]
          },
          hljs.C_LINE_COMMENT_MODE,
          hljs.C_BLOCK_COMMENT_MODE
        ]
      }
    ]
  };
}
<|endoftext|>


<commit_before>dagre.layout.order = function() {
  // External configuration
  var
    // Maximum number of passes to make
    iterations = 24,

    // Level 1: log time spent and best cross count found
    // Level 2: log cross count on each iteration
    debugLevel = 0;

  var self = {};

  self.iterations = function(x) {
    if (!arguments.length) return iterations;
    iterations = x;
    return self;
  }

  self.debugLevel = function(x) {
    if (!arguments.length) return debugLevel;
    debugLevel = x;
    return self;
  }

  self.run = function(g) {
    var timer = createTimer();

    var layering = initOrder(g);
    var bestLayering = copyLayering(layering);
    var bestCC = crossCount(g, layering);

    if (debugLevel >= 2) {
      console.log("Order phase start cross count: " + bestCC);
    }

    var cc;
    for (var i = 0; i < iterations; ++i) {
      improveOrdering(g, i, layering);
      cc = crossCount(g, layering);
      if (cc < bestCC) {
        bestLayering = copyLayering(layering);
        bestCC = cc;
      }
      if (debugLevel >= 2) {
        console.log("Order phase iter " + i + " cross count: " + bestCC);
      }
    }

    bestLayering.forEach(function(layer) {
      layer.forEach(function(u, i) {
        g.node(u).order = i;
      });
    });

    if (debugLevel >= 1) {
      console.log("Order phase time: " + timer.elapsedString());
      console.log("Order phase best cross count: " + bestCC);
    }

    return bestLayering;
  }

  return self;

  function initOrder(g) {
    var layering = [];
    var visited = {};

    function dfs(u) {
      if (u in visited) {
        return;
      }
      visited[u] = true;

      var rank = g.node(u).rank;
      for (var i = layering.length; i <= rank; ++i) {
        layering[i] = [];
      }
      layering[rank].push(u);

      g.neighbors(u).forEach(function(v) {
        dfs(v);
      });
    }

    var nodes = g.nodes().sort(function(x, y) {
      return g.node(x).rank - g.node(y).rank;
    });

    nodes.forEach(function(u) {
      dfs(u);
    });

    return layering;
  }

  function improveOrdering(g, i, layering) {
    if (i % 2 === 0) {
      for (var j = 1; j < layering.length; ++j) {
        improveLayer(g, i, layering[j - 1], layering[j], "inEdges");
      }
    } else {
      for (var j = layering.length - 2; j >= 0; --j) {
        improveLayer(g, i, layering[j + 1], layering[j], "outEdges");
      }
    }
  }

  /*
   * Given a fixed layer and a movable layer in a graph this function will
   * attempt to find an improved ordering for the movable layer such that
   * edge crossings may be reduced.
   *
   * This algorithm is based on the barycenter method.
   */
  function improveLayer(g, i, fixed, movable, neighbors) {
    var weights = rankWeights(g, fixed, movable, neighbors);

    var toSort = [];

    movable.forEach(function(u, i) {
      var weight = weights[u];
      if (weight !== -1) {
        toSort.push({node: u, weight: weight, pos: i});
      }
    });

    toSort.sort(function(x, y) {
      var d = x.weight - y.weight;
      if (d === 0) {
        return x.pos - y.pos;
      }
      return d;
    });

    var toSortIndex = 0;
    for (var i = 0; i < movable.length; ++i) {
      var u = movable[i];
      var weight = weights[u];
      if (weight !== -1) {
        movable[i] = toSort[toSortIndex++].node;
      }
    }
  }

  /*
   * Given a fixed layer and a movable layer in a graph, this function will
   * return weights for the movable layer that can be used to reorder the layer
   * for potentially reduced edge crossings.
   */
  function rankWeights(g, fixed, movable, neighbors) {
    var fixedPos = {};
    fixed.forEach(function(u, i) { fixedPos[u] = i; });

    var weights = {};
    movable.forEach(function(u) {
      var weight = -1;
      var edges = g[neighbors](u);
      if (edges.length > 0) {
        weight = 0;
        edges.forEach(function(e) {
          var source = g.source(e);
          var neighborId = g.source(e) === u ? g.target(e) : source;
          weight += fixedPos[neighborId];
        });
        weight = weight / edges.length;
      }
      weights[u] = weight;
    });

    return weights;
  }

  function copyLayering(layering) {
    return layering.map(function(l) { return l.slice(0); });
  }
}

/*
 * This function searches through a ranked and ordered graph and counts the
 * number of edges that cross. This algorithm is derived from:
 *
 *    W. Barth et al., Bilayer Cross Counting, JGAA, 8(2) 179–194 (2004)
 */
var crossCount = dagre.layout.order.crossCount = function(g, layering) {
  var cc = 0;
  var prevLayer;
  layering.forEach(function(layer) {
    if (prevLayer) {
      cc += bilayerCrossCount(g, prevLayer, layer);
    }
    prevLayer = layer;
  });
  return cc;
}

var bilayerCrossCount = dagre.layout.order.bilayerCrossCount = function(g, layer1, layer2, weightFunc) {
  if (!weightFunc) { weightFunc = function() { return 1; }; }

  var layer2Pos = {};
  layer2.forEach(function(u, i) { layer2Pos[u] = i; });

  var edges = [];
  layer1.forEach(function(u) {
    var nodeEdges = [];
    g.outEdges(u).forEach(function(e) {
      nodeEdges.push({ edge: e, pos: layer2Pos[g.target(e)] });
    });
    // TODO consider radix sort
    nodeEdges.sort(function(x, y) { return x.pos - y.pos; });
    edges = edges.concat(nodeEdges);
  });

  var firstIndex = 1;
  while (firstIndex < layer2.length) {
    firstIndex <<= 1;
  }

  var treeSize = 2 * firstIndex - 1;
  firstIndex -= 1;

  var tree = [];
  for (var i = 0; i < treeSize; ++i) { tree[i] = 0; }

  var cc = 0;
  edges.forEach(function(edge) {
    var edgeWeight = weightFunc(edge.edge);
    var treeIndex = edge.pos + firstIndex;
    tree[treeIndex] += edgeWeight;
    var weightSum = 0;
    while (treeIndex > 0) {
      if (treeIndex % 2) {
        weightSum += tree[treeIndex + 1];
      }
      treeIndex = (treeIndex - 1) >> 1;
      tree[treeIndex] += edgeWeight;
    }
    cc += edgeWeight * weightSum;
  });

  return cc;
}
<commit_msg>Do cross counting while ordering layers<commit_after>dagre.layout.order = function() {
  // External configuration
  var
    // Maximum number of passes to make
    iterations = 24,

    // Level 1: log time spent and best cross count found
    // Level 2: log cross count on each iteration
    debugLevel = 0;

  var self = {};

  self.iterations = function(x) {
    if (!arguments.length) return iterations;
    iterations = x;
    return self;
  }

  self.debugLevel = function(x) {
    if (!arguments.length) return debugLevel;
    debugLevel = x;
    return self;
  }

  self.run = function(g) {
    var timer = createTimer();

    var layering = initOrder(g);
    var bestLayering = copyLayering(layering);
    var bestCC = crossCount(g, layering);

    if (debugLevel >= 2) {
      console.log("Order phase start cross count: " + bestCC);
    }

    var cc;
    for (var i = 0; i < iterations; ++i) {
      cc = improveOrdering(g, i, layering);
      if (cc < bestCC) {
        bestLayering = copyLayering(layering);
        bestCC = cc;
      }
      if (debugLevel >= 2) {
        console.log("Order phase iter " + i + " cross count: " + bestCC);
      }
    }

    bestLayering.forEach(function(layer) {
      layer.forEach(function(u, i) {
        g.node(u).order = i;
      });
    });

    if (debugLevel >= 1) {
      console.log("Order phase time: " + timer.elapsedString());
      console.log("Order phase best cross count: " + bestCC);
    }

    return bestLayering;
  }

  return self;

  function initOrder(g) {
    var layering = [];
    var visited = {};

    function dfs(u) {
      if (u in visited) {
        return;
      }
      visited[u] = true;

      var rank = g.node(u).rank;
      for (var i = layering.length; i <= rank; ++i) {
        layering[i] = [];
      }
      layering[rank].push(u);

      g.neighbors(u).forEach(function(v) {
        dfs(v);
      });
    }

    var nodes = g.nodes().sort(function(x, y) {
      return g.node(x).rank - g.node(y).rank;
    });

    nodes.forEach(function(u) {
      dfs(u);
    });

    return layering;
  }

  function improveOrdering(g, i, layering) {
    var cc = 0;
    if (i % 2 === 0) {
      for (var j = 1; j < layering.length; ++j) {
        cc += improveLayer(g, i, layering[j - 1], layering[j], "inEdges");
      }
    } else {
      for (var j = layering.length - 2; j >= 0; --j) {
        cc += improveLayer(g, i, layering[j + 1], layering[j], "outEdges");
      }
    }
    return cc;
  }

  /*
   * Given a fixed layer and a movable layer in a graph this function will
   * attempt to find an improved ordering for the movable layer such that
   * edge crossings may be reduced.
   *
   * This algorithm is based on the barycenter method.
   */
  function improveLayer(g, i, fixed, movable, neighbors) {
    var weights = rankWeights(g, fixed, movable, neighbors);

    var toSort = [];

    movable.forEach(function(u, i) {
      var weight = weights[u];
      if (weight !== -1) {
        toSort.push({node: u, weight: weight, pos: i});
      }
    });

    toSort.sort(function(x, y) {
      var d = x.weight - y.weight;
      if (d === 0) {
        return x.pos - y.pos;
      }
      return d;
    });

    var toSortIndex = 0;
    for (var i = 0; i < movable.length; ++i) {
      var u = movable[i];
      var weight = weights[u];
      if (weight !== -1) {
        movable[i] = toSort[toSortIndex++].node;
      }
    }

    return neighbors === "inEdges"
      ? bilayerCrossCount(g, fixed, movable)
      : bilayerCrossCount(g, movable, fixed);
  }

  /*
   * Given a fixed layer and a movable layer in a graph, this function will
   * return weights for the movable layer that can be used to reorder the layer
   * for potentially reduced edge crossings.
   */
  function rankWeights(g, fixed, movable, neighbors) {
    var fixedPos = {};
    fixed.forEach(function(u, i) { fixedPos[u] = i; });

    var weights = {};
    movable.forEach(function(u) {
      var weight = -1;
      var edges = g[neighbors](u);
      if (edges.length > 0) {
        weight = 0;
        edges.forEach(function(e) {
          var source = g.source(e);
          var neighborId = g.source(e) === u ? g.target(e) : source;
          weight += fixedPos[neighborId];
        });
        weight = weight / edges.length;
      }
      weights[u] = weight;
    });

    return weights;
  }

  function copyLayering(layering) {
    return layering.map(function(l) { return l.slice(0); });
  }
}

var crossCount = dagre.layout.order.crossCount = function(g, layering) {
  var cc = 0;
  var prevLayer;
  layering.forEach(function(layer) {
    if (prevLayer) {
      cc += bilayerCrossCount(g, prevLayer, layer);
    }
    prevLayer = layer;
  });
  return cc;
}

/*
 * This function searches through a ranked and ordered graph and counts the
 * number of edges that cross. This algorithm is derived from:
 *
 *    W. Barth et al., Bilayer Cross Counting, JGAA, 8(2) 179–194 (2004)
 */
var bilayerCrossCount = dagre.layout.order.bilayerCrossCount = function(g, layer1, layer2, weightFunc) {
  if (!weightFunc) { weightFunc = function() { return 1; }; }

  var layer2Pos = {};
  layer2.forEach(function(u, i) { layer2Pos[u] = i; });

  var edges = [];
  layer1.forEach(function(u) {
    var nodeEdges = [];
    g.outEdges(u).forEach(function(e) {
      nodeEdges.push({ edge: e, pos: layer2Pos[g.target(e)] });
    });
    // TODO consider radix sort
    nodeEdges.sort(function(x, y) { return x.pos - y.pos; });
    edges = edges.concat(nodeEdges);
  });

  var firstIndex = 1;
  while (firstIndex < layer2.length) {
    firstIndex <<= 1;
  }

  var treeSize = 2 * firstIndex - 1;
  firstIndex -= 1;

  var tree = [];
  for (var i = 0; i < treeSize; ++i) { tree[i] = 0; }

  var cc = 0;
  edges.forEach(function(edge) {
    var edgeWeight = weightFunc(edge.edge);
    var treeIndex = edge.pos + firstIndex;
    tree[treeIndex] += edgeWeight;
    var weightSum = 0;
    while (treeIndex > 0) {
      if (treeIndex % 2) {
        weightSum += tree[treeIndex + 1];
      }
      treeIndex = (treeIndex - 1) >> 1;
      tree[treeIndex] += edgeWeight;
    }
    cc += edgeWeight * weightSum;
  });

  return cc;
}
<|endoftext|>


<commit_before>/*
TODO:
-better serialization/deserialization
-error handling if firebase contains malformed data, since we're not the only
ones who can write to it.
-multi part keys
*/

foam.CLASS({
  package: 'com.firebase',
  name: 'FirebaseDAO',
  extends: 'foam.dao.AbstractDAO',

  requires: [
    'foam.dao.ArraySink',
    'foam.net.HTTPRequest',
    'com.firebase.FirebaseEventSource',
    'foam.mlang.predicate.Gt',
    'foam.mlang.predicate.Constant'
  ],

  properties: [
    'of',
    'apppath',
    'secret',
    'eventSource_',
    {
      name: 'timestampProperty'
    },
    {
      name: 'basepath',
      expression: function(apppath, of) {
        return apppath + of.id.replace(/\./g, '/');
      }
    },
    {
      class: 'Boolean',
      name: 'enableStreaming',
      value: true
    },
    'startEventsAt_'
  ],

  methods: [
    function put(obj) {
      var req = this.HTTPRequest.create();

      if ( obj.id ) {
        req.method = "PUT";
        req.url = this.basepath
          + "/"
          + encodeURIComponent(obj.id) + ".json";
      } else {
        throw new Error('Server generated IDs not supported.');
        // req.method = 'POST';
        // req.url = this.basepath + '.json';
      }

      if ( this.secret ) {
        req.url += '?auth=' + encodeURIComponent(this.secret);
      }

      req.payload = JSON.stringify({
        data: foam.json.stringify(obj),
        lastUpdate: {
          ".sv": "timestamp"
        }
      });
      req.headers['content-type'] = 'application/json';
      req.headers['accept']       = 'application/json';

      return req.send().then(function(resp) {
        return resp.payload;
      }).then(function(payload) {
        payload = JSON.parse(payload);

        //        if ( obj.id ) {
          var o2 = foam.json.parse(foam.json.parseString(payload.data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(o2, payload.lastUpdate);
          }
          return o2;
        //        } else {
        //           Server created id
        //        }
      }.bind(this), function(resp) {
        // TODO: Handle various errors.
        return Promise.reject(foam.dao.InternalException.create());
      });
    },

    function remove(obj) {
      var req = this.HTTPRequest.create();
      req.method = 'DELETE',
      req.url = this.basepath + "/" + encodeURIComponent(obj.id) + ".json";

      if ( this.secret ) {
        req.url += "?auth=" + encodeURIComponent(this.secret);
      }

      return req.send().then(function() {
        return Promise.resolve();
      }, function() {
        return Promise.reject(foam.dao.InternalException.create());
      });
    },

    function find(id) {
      var req = this.HTTPRequest.create();
      req.method = "GET";
      req.url = this.basepath + "/" + encodeURIComponent(id) + ".json";
      if ( this.secret ) {
        req.url += "?auth=" + encodeURIComponent(this.secret);
      }

      return req.send().then(function(resp) {
        return resp.payload;
      }).then(function(data) {
        if ( data == "null" ) {
          return Promise.reject(foam.dao.ObjectNotFoundException.create({ id: id }));
        }
        try {
          data = JSON.parse(data);

          var obj = foam.json.parse(
            foam.json.parseString(data.data));

          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data.lastUpdate);
          }

          return obj;
        } catch(e) {
          return Promise.reject(foam.dao.InternalException.create());
        }
      }.bind(this));
    },

    function startEvents() {
      if ( this.eventSource_ || ! this.enableStreaming ) {
        return;
      }

      var params = [];
      if ( this.secret ) params.push(['auth', this.secret]);
      if ( this.startEventsAt_ ) {
        params.push(['orderBy', '"lastUpdate"']);
        params.push(['startAt', this.startEventsAt_]);
      }

      var uri = this.basepath + '.json';
      if ( params.length ) {
        uri += '?' + params.map(function(p) { return p.map(encodeURIComponent).join('='); }).join('&');
      }

      this.eventSource_ = this.FirebaseEventSource.create({
        uri: uri
      });

      this.eventSource_.put.sub(this.onPut);
      this.eventSource_.patch.sub(this.onPatch);
      this.eventSource_.start();
    },

    function stopEvents() {
      if ( this.eventSource_ ) {
        this.eventSource_.close();
        this.eventSource_.message.put.unsub(this.onPut);
        this.eventSource_.message.patch.unsub(this.onPatch);
        this.clearProperty('eventSource_');
      }
    },

    function select(sink, skip, limit, order, predicate) {
      var req = this.HTTPRequest.create();
      req.method = "GET";

      var params = [];
      if ( this.secret ) params.push(['auth', this.secret]);

      // Efficiently handle GT(lastupdate, #) queries.  Used by the SyncDAO to get
      // all changes.

      if ( predicate && this.timestampProperty &&
           this.Gt.isInstance(predicate) &&
           this.Constant.isInstance(predicate.arg2) &&
           predicate.arg1 === this.timestampProperty ) {

        // TODO: This is a hack to ensure that
        if ( ! this.startEventsAt_ )  {
          this.startEventsAt_ = predicate.arg2.f() + 1;
          this.startEvents();
        }

        params.push(['orderBy', '"lastUpdate"']);
        params.push(['startAt', predicate.arg2.f() + 1]);
      }

      var url = this.basepath + '.json';
      if ( params.length ) {
        url += '?' + params.map(function(p) { return p.map(encodeURIComponent).join('='); }).join('&');
      }

      req.url = url;

      var resultSink = sink || this.ArraySink.create();
      sink = this.decorateSink_(resultSink, skip, limit, order, predicate);

      // TODO: This should be streamed for better handling of large responses.
      return req.send().then(function(resp) {
        if ( ! resp.success ) {
          return Promise.reject(foam.dao.InternalException.create());
        }
        return resp.payload;
      }).then(function(payload) {
        var data = JSON.parse(payload);
        var fc = this.FlowControl.create();

        for ( var key in data ) {
          if ( fc.stopped ) break;
          if ( fc.errorEvt ) {
            sink.error && sink.error(fc.errorEvt);
            future.set(sink);
            break;
          }

          var obj = foam.json.parse(
            foam.json.parseString(data[key].data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data[key].lastUpdate);
          }

          sink.put(obj, null, fc);
        }
        sink.eof();

        return resultSink;
      }.bind(this), function(resp) {
        var e = foam.dao.InternalException.create();
        sink.error(e);
        return Promise.reject(e);
      });
    }
  ],

  listeners: [
    function onPut(s, _, data) {
      // PATH is one of
      // / -> new objects
      // /key -> new object
      // /key/data -> updated object

      var path = data.path;
      if ( path == "/" ) {
        // All data removed?
        if ( data.data == null ) {
          this.on.reset.pub();
          return;
        }

        for ( var key in data.data ) {
          var obj = foam.json.parse(foam.json.parseString(data.data[key].data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data.data[key].lastUpdate);
          }
          this.on.put.pub(obj);
        }
        return;
      } else if ( path.lastIndexOf('/') === 0 ) {
        if ( data.data == null ) {
          var obj = this.of.create();
          obj.id = path.substring(1)
          this.on.remove.pub(obj);
          return;
        }
        var obj = foam.json.parse(foam.json.parseString(data.data.data));
        if ( this.timestampProperty ) {
          this.timestampProperty.set(obj, data.data.lastUpdate);
        }
        this.on.put.pub(obj);
      } else if ( path.indexOf('/data') === path.length - 5 ) {
        // These last two events shouldn't happen unless somebody is editing
        // the underlying firebase data by hand.

        // Data of an existing row updated.
        debugger;
        var id = path.substring(1);
        id = id.substring(0, id.indexOf('/'));
        this.find(id).then(function(obj) {
          this.on.put.pub(obj);
        }.bind(this));

        // var obj = foam.json.parse(foam.json.parseString(data.data));
        // this.on.put.pub(obj);
      } else if ( path.indexOf('/lastUpdate') === path.length - 11 ) {
        // Timestamp of an existing row updated, do anything?
        // presumably if the object itself hasn't been updated we don't care
        // if it has been updated we should get an event for that.

        debugger;
        var id = path.substring(1);
        id = id.substring(0, id.indexOf('/'));
        this.find(id).then(function(obj) {
          this.on.put.pub(obj);
        }.bind(this));
      }
    },

    function onPatch(s, _, _, data) {
          // TODO: What does a patch even look like?
      debugger;
    }
  ]
});

foam.CLASS({
  package: 'com.firebase',
  name: 'SafariFirebaseDAO',
  extends: 'com.firebase.FirebaseDAO',

  requires: [
    'foam.net.XHRHTTPRequest as HTTPRequest',
    'foam.net.SafariEventSource as EventSource'
  ],

  properties: [
    [ 'enableStreaming', false ]
  ]
});

foam.CLASS({
  package: 'com.firebase',
  name: 'FirebaseEventSource',
  requires: [
    'foam.net.EventSource'
  ],
  properties: [
    {
      name: 'uri',
      required: true
    },
    {
      name: 'eventSource',
      postSet: function(old, nu) {
        nu.message.sub(this.onMessage);
      },
      factory: function() {
        return this.EventSource.create({
          uri: this.uri
        });
      }
    },
    {
      class: 'String',
      name: 'buffer'
    }
  ],
  topics: [
    'put',
    'patch',
    'keep-alive',
    'cancel',
    'auth_revoked'
  ],
  methods: [
    function start() {
      this.eventSource.start();
    }
  ],
  listeners: [
    function onMessage(s, msg, name, data) {
      switch(name) {
      case 'put':
        this.onPut(name, data);
        break;
      case 'patch':
        this.onPatch(name, data);
        break;
      case 'keep-alive':
        this.onKeepAlive(name, data);
        break;
      case 'cancel':
        this.onCancel(name, data);
        break;
      case 'auth_revoked':
        this.onAuthRevoked(name, data);
        break;
      default:
        this.onUnknown(name, data);
      }
    },
    function onPut(name, data) {
      this.put.pub(JSON.parse(data));
      return;

      // this.buffer += data;
      // try {
      //   var payload = JSON.parse(this.buffer);
      // } catch(e) {
      //   this.warn('Failed to parse payload, assuming its incomplete.', e, this.buffer.length);
      //   return;
      // }

      // this.buffer = '';
      // this.put.pub(payload);
    },
    function onPatch() {
      debugger;
    },
    function onKeepAlive() {
    },
    function onCancel() {
    },
    function onUnknown(name, data) {
      this.warn('Unknown firebase event', name, data);
    }
  ]
});
<commit_msg>Added copyright notice.<commit_after>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
TODO:
-better serialization/deserialization
-error handling if firebase contains malformed data, since we're not the only
ones who can write to it.
-multi part keys
*/

foam.CLASS({
  package: 'com.firebase',
  name: 'FirebaseDAO',
  extends: 'foam.dao.AbstractDAO',

  requires: [
    'foam.dao.ArraySink',
    'foam.net.HTTPRequest',
    'com.firebase.FirebaseEventSource',
    'foam.mlang.predicate.Gt',
    'foam.mlang.predicate.Constant'
  ],

  properties: [
    'of',
    'apppath',
    'secret',
    'eventSource_',
    {
      name: 'timestampProperty'
    },
    {
      name: 'basepath',
      expression: function(apppath, of) {
        return apppath + of.id.replace(/\./g, '/');
      }
    },
    {
      class: 'Boolean',
      name: 'enableStreaming',
      value: true
    },
    'startEventsAt_'
  ],

  methods: [
    function put(obj) {
      var req = this.HTTPRequest.create();

      if ( obj.id ) {
        req.method = "PUT";
        req.url = this.basepath
          + "/"
          + encodeURIComponent(obj.id) + ".json";
      } else {
        throw new Error('Server generated IDs not supported.');
        // req.method = 'POST';
        // req.url = this.basepath + '.json';
      }

      if ( this.secret ) {
        req.url += '?auth=' + encodeURIComponent(this.secret);
      }

      req.payload = JSON.stringify({
        data: foam.json.stringify(obj),
        lastUpdate: {
          ".sv": "timestamp"
        }
      });
      req.headers['content-type'] = 'application/json';
      req.headers['accept']       = 'application/json';

      return req.send().then(function(resp) {
        return resp.payload;
      }).then(function(payload) {
        payload = JSON.parse(payload);

        //        if ( obj.id ) {
          var o2 = foam.json.parse(foam.json.parseString(payload.data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(o2, payload.lastUpdate);
          }
          return o2;
        //        } else {
        //           Server created id
        //        }
      }.bind(this), function(resp) {
        // TODO: Handle various errors.
        return Promise.reject(foam.dao.InternalException.create());
      });
    },

    function remove(obj) {
      var req = this.HTTPRequest.create();
      req.method = 'DELETE',
      req.url = this.basepath + "/" + encodeURIComponent(obj.id) + ".json";

      if ( this.secret ) {
        req.url += "?auth=" + encodeURIComponent(this.secret);
      }

      return req.send().then(function() {
        return Promise.resolve();
      }, function() {
        return Promise.reject(foam.dao.InternalException.create());
      });
    },

    function find(id) {
      var req = this.HTTPRequest.create();
      req.method = "GET";
      req.url = this.basepath + "/" + encodeURIComponent(id) + ".json";
      if ( this.secret ) {
        req.url += "?auth=" + encodeURIComponent(this.secret);
      }

      return req.send().then(function(resp) {
        return resp.payload;
      }).then(function(data) {
        if ( data == "null" ) {
          return Promise.reject(foam.dao.ObjectNotFoundException.create({ id: id }));
        }
        try {
          data = JSON.parse(data);

          var obj = foam.json.parse(
            foam.json.parseString(data.data));

          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data.lastUpdate);
          }

          return obj;
        } catch(e) {
          return Promise.reject(foam.dao.InternalException.create());
        }
      }.bind(this));
    },

    function startEvents() {
      if ( this.eventSource_ || ! this.enableStreaming ) {
        return;
      }

      var params = [];
      if ( this.secret ) params.push(['auth', this.secret]);
      if ( this.startEventsAt_ ) {
        params.push(['orderBy', '"lastUpdate"']);
        params.push(['startAt', this.startEventsAt_]);
      }

      var uri = this.basepath + '.json';
      if ( params.length ) {
        uri += '?' + params.map(function(p) { return p.map(encodeURIComponent).join('='); }).join('&');
      }

      this.eventSource_ = this.FirebaseEventSource.create({
        uri: uri
      });

      this.eventSource_.put.sub(this.onPut);
      this.eventSource_.patch.sub(this.onPatch);
      this.eventSource_.start();
    },

    function stopEvents() {
      if ( this.eventSource_ ) {
        this.eventSource_.close();
        this.eventSource_.message.put.unsub(this.onPut);
        this.eventSource_.message.patch.unsub(this.onPatch);
        this.clearProperty('eventSource_');
      }
    },

    function select(sink, skip, limit, order, predicate) {
      var req = this.HTTPRequest.create();
      req.method = "GET";

      var params = [];
      if ( this.secret ) params.push(['auth', this.secret]);

      // Efficiently handle GT(lastupdate, #) queries.  Used by the SyncDAO to get
      // all changes.

      if ( predicate && this.timestampProperty &&
           this.Gt.isInstance(predicate) &&
           this.Constant.isInstance(predicate.arg2) &&
           predicate.arg1 === this.timestampProperty ) {

        // TODO: This is a hack to ensure that
        if ( ! this.startEventsAt_ )  {
          this.startEventsAt_ = predicate.arg2.f() + 1;
          this.startEvents();
        }

        params.push(['orderBy', '"lastUpdate"']);
        params.push(['startAt', predicate.arg2.f() + 1]);
      }

      var url = this.basepath + '.json';
      if ( params.length ) {
        url += '?' + params.map(function(p) { return p.map(encodeURIComponent).join('='); }).join('&');
      }

      req.url = url;

      var resultSink = sink || this.ArraySink.create();
      sink = this.decorateSink_(resultSink, skip, limit, order, predicate);

      // TODO: This should be streamed for better handling of large responses.
      return req.send().then(function(resp) {
        if ( ! resp.success ) {
          return Promise.reject(foam.dao.InternalException.create());
        }
        return resp.payload;
      }).then(function(payload) {
        var data = JSON.parse(payload);
        var fc = this.FlowControl.create();

        for ( var key in data ) {
          if ( fc.stopped ) break;
          if ( fc.errorEvt ) {
            sink.error && sink.error(fc.errorEvt);
            future.set(sink);
            break;
          }

          var obj = foam.json.parse(
            foam.json.parseString(data[key].data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data[key].lastUpdate);
          }

          sink.put(obj, null, fc);
        }
        sink.eof();

        return resultSink;
      }.bind(this), function(resp) {
        var e = foam.dao.InternalException.create();
        sink.error(e);
        return Promise.reject(e);
      });
    }
  ],

  listeners: [
    function onPut(s, _, data) {
      // PATH is one of
      // / -> new objects
      // /key -> new object
      // /key/data -> updated object

      var path = data.path;
      if ( path == "/" ) {
        // All data removed?
        if ( data.data == null ) {
          this.on.reset.pub();
          return;
        }

        for ( var key in data.data ) {
          var obj = foam.json.parse(foam.json.parseString(data.data[key].data));
          if ( this.timestampProperty ) {
            this.timestampProperty.set(obj, data.data[key].lastUpdate);
          }
          this.on.put.pub(obj);
        }
        return;
      } else if ( path.lastIndexOf('/') === 0 ) {
        if ( data.data == null ) {
          var obj = this.of.create();
          obj.id = path.substring(1)
          this.on.remove.pub(obj);
          return;
        }
        var obj = foam.json.parse(foam.json.parseString(data.data.data));
        if ( this.timestampProperty ) {
          this.timestampProperty.set(obj, data.data.lastUpdate);
        }
        this.on.put.pub(obj);
      } else if ( path.indexOf('/data') === path.length - 5 ) {
        // These last two events shouldn't happen unless somebody is editing
        // the underlying firebase data by hand.

        // Data of an existing row updated.
        debugger;
        var id = path.substring(1);
        id = id.substring(0, id.indexOf('/'));
        this.find(id).then(function(obj) {
          this.on.put.pub(obj);
        }.bind(this));

        // var obj = foam.json.parse(foam.json.parseString(data.data));
        // this.on.put.pub(obj);
      } else if ( path.indexOf('/lastUpdate') === path.length - 11 ) {
        // Timestamp of an existing row updated, do anything?
        // presumably if the object itself hasn't been updated we don't care
        // if it has been updated we should get an event for that.

        debugger;
        var id = path.substring(1);
        id = id.substring(0, id.indexOf('/'));
        this.find(id).then(function(obj) {
          this.on.put.pub(obj);
        }.bind(this));
      }
    },

    function onPatch(s, _, _, data) {
          // TODO: What does a patch even look like?
      debugger;
    }
  ]
});

foam.CLASS({
  package: 'com.firebase',
  name: 'SafariFirebaseDAO',
  extends: 'com.firebase.FirebaseDAO',

  requires: [
    'foam.net.XHRHTTPRequest as HTTPRequest',
    'foam.net.SafariEventSource as EventSource'
  ],

  properties: [
    [ 'enableStreaming', false ]
  ]
});

foam.CLASS({
  package: 'com.firebase',
  name: 'FirebaseEventSource',
  requires: [
    'foam.net.EventSource'
  ],
  properties: [
    {
      name: 'uri',
      required: true
    },
    {
      name: 'eventSource',
      postSet: function(old, nu) {
        nu.message.sub(this.onMessage);
      },
      factory: function() {
        return this.EventSource.create({
          uri: this.uri
        });
      }
    },
    {
      class: 'String',
      name: 'buffer'
    }
  ],
  topics: [
    'put',
    'patch',
    'keep-alive',
    'cancel',
    'auth_revoked'
  ],
  methods: [
    function start() {
      this.eventSource.start();
    }
  ],
  listeners: [
    function onMessage(s, msg, name, data) {
      switch(name) {
      case 'put':
        this.onPut(name, data);
        break;
      case 'patch':
        this.onPatch(name, data);
        break;
      case 'keep-alive':
        this.onKeepAlive(name, data);
        break;
      case 'cancel':
        this.onCancel(name, data);
        break;
      case 'auth_revoked':
        this.onAuthRevoked(name, data);
        break;
      default:
        this.onUnknown(name, data);
      }
    },
    function onPut(name, data) {
      this.put.pub(JSON.parse(data));
      return;

      // this.buffer += data;
      // try {
      //   var payload = JSON.parse(this.buffer);
      // } catch(e) {
      //   this.warn('Failed to parse payload, assuming its incomplete.', e, this.buffer.length);
      //   return;
      // }

      // this.buffer = '';
      // this.put.pub(payload);
    },
    function onPatch() {
      debugger;
    },
    function onKeepAlive() {
    },
    function onCancel() {
    },
    function onUnknown(name, data) {
      this.warn('Unknown firebase event', name, data);
    }
  ]
});
<|endoftext|>


<commit_before>import store from '../store'

const realtime = {
  createNewSource: () => {
    return new EventSource('/events')
  },

  init: (source) => {
    realtime.subscribe(source, 'comment:new', (eventData) => {
      const commentId = eventData.id
      store.dispatch('loadComment', {id: commentId})
    })
    return source
  },

  subscribe: (source, eventName, listener) => {
    source.addEventListener(eventName, (event) => {
      const data = JSON.parse(event.data)
      listener(data.data)
    }, false)
    return source
  }
}

export default realtime
<commit_msg>Listen to more events<commit_after>import store from '../store'

const realtime = {
  createNewSource: () => {
    return new EventSource('/events')
  },

  init: (source) => {
    realtime.subscribe(source, 'comment:new', (eventData) => {
      const commentId = eventData.id
      store.dispatch('loadComment', {id: commentId})
    })
    realtime.subscribe(source, 'task:assign', (eventData) => {
      store.dispatch('loadTodos')
    })
    realtime.subscribe(source, 'preview:add', (eventData) => {
      store.commit('ADD_PREVIEW_END', {
        preview: eventData.preview,
        taskId: eventData.task_id,
        commentId: eventData.comment_id
      })
    })

    return source
  },

  subscribe: (source, eventName, listener) => {
    source.addEventListener(eventName, (event) => {
      const data = JSON.parse(event.data)
      listener(data.data)
    }, false)
    return source
  }
}

export default realtime
<|endoftext|>


<commit_before>var _ = require('lodash'),
    Promise = require('bluebird');

module.exports.show = function(params) {
  var path = "/statuses/show.json?id=" + params.id;
  return this.get(path, params);
};

module.exports.lookup = function(params) {
  var self = this;
  var ids = _.chunk(params.id, 100);
  delete params.id;

  return Promise.resolve(ids)
  .map(function(ids) {
    var path = "/statuses/lookup.json?id=" + ids;
    return self.get(path, params)
    .then(function(res) {return { data: res };})
    .catch(function(e)  {return { error: e };});
  }).reduce(function(obj, res) {
    if (res.data) {
      obj.data.push(res.data);
    }
    if (res.error) {
      obj.errors.push(res.error);
    }
    return obj;
  }, {data: [], errors: []})
  .then(function(result) {
    result.data = _.flatten(result.data);
    result.errors = _.flatten(result.errors);
    return result;
  });
};
<commit_msg>Add user timeline API method.<commit_after>var _ = require('lodash'),
    Promise = require('bluebird');

module.exports.userTimeline = function(params) {
  return this.get("/statuses/user_timeline.json", params);
}

module.exports.show = function(params) {
  var path = "/statuses/show.json?id=" + params.id;
  return this.get(path, params);
};

module.exports.lookup = function(params) {
  var self = this;
  var ids = _.chunk(params.id, 100);
  delete params.id;

  return Promise.resolve(ids)
  .map(function(ids) {
    var path = "/statuses/lookup.json?id=" + ids;
    return self.get(path, params)
    .then(function(res) {return { data: res };})
    .catch(function(e)  {return { error: e };});
  }).reduce(function(obj, res) {
    if (res.data) {
      obj.data.push(res.data);
    }
    if (res.error) {
      obj.errors.push(res.error);
    }
    return obj;
  }, {data: [], errors: []})
  .then(function(result) {
    result.data = _.flatten(result.data);
    result.errors = _.flatten(result.errors);
    return result;
  });
};
<|endoftext|>


<commit_before>/* @flow */

import { info, track, flush as flushLogs } from 'beaver-logger/client';

import { FPTI } from '../constants';

import { match } from './util';
import { getStorageState, getStorageID, getSessionState } from './session';

function isCheckpointUnique(name : string) : boolean {
    return getSessionState(state => {
        state.loggedBeacons = state.loggedBeacons || [];

        if (state.loggedBeacons.indexOf(name) === -1) {
            state.loggedBeacons.push(name);
            return true;
        }

        return false;
    });
}

type Throttle = {
    isEnabled : () => boolean,
    isDisabled : () => boolean,
    getTreatment : () => string,
    log : (string, payload? : { [string] : ?string }) => Throttle,
    logStart : (payload? : { [string] : ?string }) => Throttle,
    logComplete : (payload? : { [string] : ?string }) => Throttle
};

function getThrottlePercentile(name : string) : number {
    return getStorageState(storage => {
        storage.throttlePercentiles = storage.throttlePercentiles || {};
        storage.throttlePercentiles[name] = storage.throttlePercentiles[name] || Math.floor(Math.random() * 100);
        return storage.throttlePercentiles[name];
    });
}

export function getThrottle(name : string, sample : number) : Throttle {

    let uid = getStorageID();

    let throttle = getThrottlePercentile(name);

    let group;

    if (throttle < sample) {
        group = 'test';
    } else if ((sample >= 50) || ((sample <= throttle) && (throttle < (sample * 2)))) {
        group = 'control';
    } else {
        group = 'throttle';
    }

    let treatment = `${ name }_${ group }`;

    let started = false;
    let forced = false;

    try {
        if (window.localStorage && window.localStorage.getItem(name)) {
            forced = true;
        }
    } catch (err) {
        // pass
    }

    return {

        isEnabled() : boolean {
            return (group === 'test') || forced;
        },

        isDisabled() : boolean {
            return (group !== 'test') && !forced;
        },

        getTreatment() : string {
            return treatment;
        },

        log(checkpointName : string, payload? : { [string] : ?string } = {}) : Throttle {
            if (!started) {
                return this;
            }

            if (isCheckpointUnique(`${ name }_${ treatment }`)) {
                track({
                    [ FPTI.KEY.STATE ]:           FPTI.STATE.PXP,
                    [ FPTI.KEY.TRANSITION ]:      FPTI.TRANSITION.PXP,
                    [ FPTI.KEY.EXPERIMENT_NAME ]: name,
                    [ FPTI.KEY.TREATMENT_NAME ]:  treatment,
                    ...payload
                });
            }

            let event = `${ name }_${ treatment }_${ checkpointName }`;

            if (isCheckpointUnique(event)) {
                info(event, { ...payload, expuid: uid });
            }

            flushLogs();

            return this;
        },

        logStart(payload? : { [string] : ?string } = {}) : Throttle {
            started = true;
            return this.log(`start`, payload);
        },

        logComplete(payload? : { [string] : ?string } = {}) : Throttle {
            return this.log(`complete`, payload);
        }
    };
}

export function getReturnToken() : ?string {

    let token = match(window.location.href, /token=((EC-)?[A-Z0-9]+)/);
    let payer = match(window.location.href, /PayerID=([A-Z0-9]+)/);

    if (token && payer) {
        return token;
    }
}
<commit_msg>Use constants for throttle groups<commit_after>/* @flow */

import { info, track, flush as flushLogs } from 'beaver-logger/client';

import { FPTI } from '../constants';

import { match } from './util';
import { getStorageState, getStorageID, getSessionState } from './session';

function isCheckpointUnique(name : string) : boolean {
    return getSessionState(state => {
        state.loggedBeacons = state.loggedBeacons || [];

        if (state.loggedBeacons.indexOf(name) === -1) {
            state.loggedBeacons.push(name);
            return true;
        }

        return false;
    });
}

type Throttle = {
    isEnabled : () => boolean,
    isDisabled : () => boolean,
    getTreatment : () => string,
    log : (string, payload? : { [string] : ?string }) => Throttle,
    logStart : (payload? : { [string] : ?string }) => Throttle,
    logComplete : (payload? : { [string] : ?string }) => Throttle
};

function getThrottlePercentile(name : string) : number {
    return getStorageState(storage => {
        storage.throttlePercentiles = storage.throttlePercentiles || {};
        storage.throttlePercentiles[name] = storage.throttlePercentiles[name] || Math.floor(Math.random() * 100);
        return storage.throttlePercentiles[name];
    });
}

const THROTTLE_GROUP = {
    TEST:     'test',
    CONTROL:  'control',
    THROTTLE: 'throttle'
};

export function getThrottle(name : string, sample : number) : Throttle {

    let uid = getStorageID();

    let throttle = getThrottlePercentile(name);

    let group;

    if (throttle < sample) {
        group = THROTTLE_GROUP.TEST;
    } else if ((sample >= 50) || ((sample <= throttle) && (throttle < (sample * 2)))) {
        group = THROTTLE_GROUP.CONTROL;
    } else {
        group = THROTTLE_GROUP.THROTTLE;
    }

    let treatment = `${ name }_${ group }`;

    let started = false;
    let forced = false;

    try {
        if (window.localStorage && window.localStorage.getItem(name)) {
            forced = true;
        }
    } catch (err) {
        // pass
    }

    return {

        isEnabled() : boolean {
            return (group === THROTTLE_GROUP.TEST) || forced;
        },

        isDisabled() : boolean {
            return (group !== THROTTLE_GROUP.TEST) && !forced;
        },

        getTreatment() : string {
            return treatment;
        },

        log(checkpointName : string, payload? : { [string] : ?string } = {}) : Throttle {
            if (!started) {
                return this;
            }

            if (isCheckpointUnique(`${ name }_${ treatment }`)) {
                track({
                    [ FPTI.KEY.STATE ]:           FPTI.STATE.PXP,
                    [ FPTI.KEY.TRANSITION ]:      FPTI.TRANSITION.PXP,
                    [ FPTI.KEY.EXPERIMENT_NAME ]: name,
                    [ FPTI.KEY.TREATMENT_NAME ]:  treatment,
                    ...payload
                });
            }

            let event = `${ name }_${ treatment }_${ checkpointName }`;

            if (isCheckpointUnique(event)) {
                info(event, { ...payload, expuid: uid });
            }

            flushLogs();

            return this;
        },

        logStart(payload? : { [string] : ?string } = {}) : Throttle {
            started = true;
            return this.log(`start`, payload);
        },

        logComplete(payload? : { [string] : ?string } = {}) : Throttle {
            return this.log(`complete`, payload);
        }
    };
}

export function getReturnToken() : ?string {

    let token = match(window.location.href, /token=((EC-)?[A-Z0-9]+)/);
    let payer = match(window.location.href, /PayerID=([A-Z0-9]+)/);

    if (token && payer) {
        return token;
    }
}
<|endoftext|>


<commit_before>window.jsLibs = [
	{
		url: 'https://code.jquery.com/jquery-3.2.1.min.js',
		label: 'jQuery',
		type: 'js'
	},
	{
		url: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js',
		label: 'Bootstrap 3',
		type: 'js'
	},
	{
		url:
			'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js',
		label: 'Bootstrap 4β',
		type: 'js'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js',
		label: 'Foundation',
		type: 'js'
	},
	{
		url: 'https://semantic-ui.com/dist/semantic.min.js',
		label: 'Semantic UI',
		type: 'js'
	},
	{
		url: 'https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js',
		label: 'Angular',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react.min.js',
		label: 'React',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js',
		label: 'React DOM',
		type: 'js'
	},
	{
		url: 'https://unpkg.com/vue@2.4.4/dist/vue.min.js',
		label: 'Vue.js',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js',
		label: 'Three.js',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.2/d3.min.js',
		label: 'D3',
		type: 'js'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js',
		label: 'Underscore',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js',
		label: 'Greensock TweenMax',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.4/js/uikit.min.js',
		label: 'UIkit 2',
		type: 'js'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.30/js/uikit.min.js',
		label: 'UIkit 3',
		type: 'js'
	}
];
window.cssLibs = [
	{
		url:
			'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css',
		label: 'Bootstrap 3',
		type: 'css'
	},
	{
		url:
			'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css',
		label: 'Bootstrap 4β',
		type: 'css'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css',
		label: 'Foundation',
		type: 'css'
	},
	{
		url: 'https://semantic-ui.com/dist/semantic.min.css',
		label: 'Semantic UI',
		type: 'css'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.0/css/bulma.min.css',
		label: 'Bulma',
		type: 'css'
	},

	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/hint.css/2.5.0/hint.min.css',
		label: 'Hint.css',
		type: 'css'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.4/css/uikit.min.css',
		label: 'UIkit 2',
		type: 'css'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.30/css/uikit.min.css',
		label: 'UIkit 3',
		type: 'css'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css',
		label: 'Animate.css',
		type: 'css'
	},
	{
		url:
			'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css',
		label: 'FontAwesome',
		type: 'css'
	}
];
<commit_msg>Update library-list.js<commit_after>window.jsLibs = [
	{
		url: 'https://code.jquery.com/jquery-3.2.1.min.js',
		label: 'jQuery',
		type: 'js'
	},
	{
		url: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js',
		label: 'Bootstrap 3',
		type: 'js'
	},
	{
		url:
			'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js',
		label: 'Bootstrap 4β',
		type: 'js'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js',
		label: 'Foundation',
		type: 'js'
	},
	{
		url: 'https://semantic-ui.com/dist/semantic.min.js',
		label: 'Semantic UI',
		type: 'js'
	},
	{
		url: 'https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js',
		label: 'Angular',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react.min.js',
		label: 'React',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js',
		label: 'React DOM',
		type: 'js'
	},
	{
		url: 'https://unpkg.com/vue@2.5.0/dist/vue.min.js',
		label: 'Vue.js',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js',
		label: 'Three.js',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.2/d3.min.js',
		label: 'D3',
		type: 'js'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js',
		label: 'Underscore',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js',
		label: 'Greensock TweenMax',
		type: 'js'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.4/js/uikit.min.js',
		label: 'UIkit 2',
		type: 'js'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.30/js/uikit.min.js',
		label: 'UIkit 3',
		type: 'js'
	}
];
window.cssLibs = [
	{
		url:
			'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css',
		label: 'Bootstrap 3',
		type: 'css'
	},
	{
		url:
			'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css',
		label: 'Bootstrap 4β',
		type: 'css'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css',
		label: 'Foundation',
		type: 'css'
	},
	{
		url: 'https://semantic-ui.com/dist/semantic.min.css',
		label: 'Semantic UI',
		type: 'css'
	},
	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.0/css/bulma.min.css',
		label: 'Bulma',
		type: 'css'
	},

	{
		url: 'https://cdnjs.cloudflare.com/ajax/libs/hint.css/2.5.0/hint.min.css',
		label: 'Hint.css',
		type: 'css'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.4/css/uikit.min.css',
		label: 'UIkit 2',
		type: 'css'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.30/css/uikit.min.css',
		label: 'UIkit 3',
		type: 'css'
	},
	{
		url:
			'https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css',
		label: 'Animate.css',
		type: 'css'
	},
	{
		url:
			'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css',
		label: 'FontAwesome',
		type: 'css'
	}
];
<|endoftext|>


<commit_before>angular.module('localStorage', ['ngCookies']).factory('$store', function ($parse, $cookieStore) {
	/**
	 * Global Vars
	 */
	var storage = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
	var supported = !(typeof storage === 'undefined' || typeof window.JSON === 'undefined');

	var privateMethods = {
		/**
		 * Pass any type of a string from the localStorage to be parsed so it returns a usable version (like an Object)
		 * @param res - a string that will be parsed for type
		 * @returns {*} - whatever the real type of stored value was
		 */
		parseValue: function (res) {
			var val;
			try {
				val = JSON.parse(res);
				if (typeof val === 'undefined') {
					val = res;
				}
				if (val === 'true') {
					val = true;
				}
				if (val === 'false') {
					val = false;
				}
				if (parseFloat(val) === val && !angular.isObject(val)) {
					val = parseFloat(val);
				}
			} catch (e) {
				val = res;
			}
			return val;
		}
	};

	var publicMethods = {
		/**
		 * Set - let's you set a new localStorage key pair set
		 * @param key - a string that will be used as the accessor for the pair
		 * @param value - the value of the localStorage item
		 * @returns {*} - will return whatever it is you've stored in the local storage
		 */
		set: function (key, value) {
			if (!supported) {
				try {
					$cookieStore.put(key, value);
					return value;
				} catch(e) {
					console.log('Local Storage not supported, make sure you have angular-cookies enabled.');
				}
			}
			var saver = JSON.stringify(value);
			storage.setItem(key, saver);
			return privateMethods.parseValue(saver);
		},

		/**
		 * Get - let's you get the value of any pair you've stored
		 * @param key - the string that you set as accessor for the pair
		 * @returns {*} - Object,String,Float,Boolean depending on what you stored
		 */
		get: function (key) {
			if (!supported) {
				try {
					return privateMethods.parseValue($.cookie(key));
				} catch (e) {
					return null;
				}
			}
			var item = storage.getItem(key);
			return privateMethods.parseValue(item);
		},

		/**
		 * Remove - let's you nuke a value from localStorage
		 * @param key - the accessor value
		 * @returns {boolean} - if everything went as planned
		 */
		remove: function (key) {
			if (!supported) {
				try {
					$cookieStore.remove(key);
					return true;
				} catch (e) {
					return false;
				}
			}
			storage.removeItem(key);
			return true;
		},

		/**
		 * Bind - let's you directly bind a localStorage value to a $scope variable
		 * @param $scope - the current scope you want the variable available in
		 * @param key - the name of the variable you are binding
		 * @param def - the default value (OPTIONAL)
		 * @returns {*} - returns whatever the stored value is
		 */
		bind: function ($scope, key, def) {
			// If no defined value for def we use empty string
			def = (angular.isUndefined(def)) ? '' : def;
			if (!publicMethods.get(key)) {
				publicMethods.set(key, def);
			}
			$parse(key).assign($scope, publicMethods.get(key));
			$scope.$watch(key, function (val) {
				publicMethods.set(key, val);
			}, true);
			return publicMethods.get(key);
		},
		/**
		 * Unbind - let's you unbind a variable from localStorage while removing the value from both
		 * the localStorage and the local variable and sets it to null
		 * @param $scope - the scope the variable was initially set in
		 * @param key - the name of the variable you are unbinding
		 */
		unbind: function($scope,key) {
			$parse(key).assign($scope, null);
			$scope.$watch(key, function () { });
			publicMethods.remove(key);
		}
	};
	return publicMethods;
});
<commit_msg>use $window module rather than global<commit_after>angular.module('localStorage', ['ngCookies']).factory('$store', function ($parse, $cookieStore, $window) {
	/**
	 * Global Vars
	 */
	var storage = (typeof $window.localStorage === 'undefined') ? undefined : $window.localStorage;
	var supported = !(typeof storage === 'undefined' || typeof $window.JSON === 'undefined');

	var privateMethods = {
		/**
		 * Pass any type of a string from the localStorage to be parsed so it returns a usable version (like an Object)
		 * @param res - a string that will be parsed for type
		 * @returns {*} - whatever the real type of stored value was
		 */
		parseValue: function (res) {
			var val;
			try {
				val = JSON.parse(res);
				if (typeof val === 'undefined') {
					val = res;
				}
				if (val === 'true') {
					val = true;
				}
				if (val === 'false') {
					val = false;
				}
				if (parseFloat(val) === val && !angular.isObject(val)) {
					val = parseFloat(val);
				}
			} catch (e) {
				val = res;
			}
			return val;
		}
	};

	var publicMethods = {
		/**
		 * Set - let's you set a new localStorage key pair set
		 * @param key - a string that will be used as the accessor for the pair
		 * @param value - the value of the localStorage item
		 * @returns {*} - will return whatever it is you've stored in the local storage
		 */
		set: function (key, value) {
			if (!supported) {
				try {
					$cookieStore.put(key, value);
					return value;
				} catch(e) {
					console.log('Local Storage not supported, make sure you have angular-cookies enabled.');
				}
			}
			var saver = JSON.stringify(value);
			storage.setItem(key, saver);
			return privateMethods.parseValue(saver);
		},

		/**
		 * Get - let's you get the value of any pair you've stored
		 * @param key - the string that you set as accessor for the pair
		 * @returns {*} - Object,String,Float,Boolean depending on what you stored
		 */
		get: function (key) {
			if (!supported) {
				try {
					return privateMethods.parseValue($.cookie(key));
				} catch (e) {
					return null;
				}
			}
			var item = storage.getItem(key);
			return privateMethods.parseValue(item);
		},

		/**
		 * Remove - let's you nuke a value from localStorage
		 * @param key - the accessor value
		 * @returns {boolean} - if everything went as planned
		 */
		remove: function (key) {
			if (!supported) {
				try {
					$cookieStore.remove(key);
					return true;
				} catch (e) {
					return false;
				}
			}
			storage.removeItem(key);
			return true;
		},

		/**
		 * Bind - let's you directly bind a localStorage value to a $scope variable
		 * @param $scope - the current scope you want the variable available in
		 * @param key - the name of the variable you are binding
		 * @param def - the default value (OPTIONAL)
		 * @returns {*} - returns whatever the stored value is
		 */
		bind: function ($scope, key, def) {
			// If no defined value for def we use empty string
			def = (angular.isUndefined(def)) ? '' : def;
			if (!publicMethods.get(key)) {
				publicMethods.set(key, def);
			}
			$parse(key).assign($scope, publicMethods.get(key));
			$scope.$watch(key, function (val) {
				publicMethods.set(key, val);
			}, true);
			return publicMethods.get(key);
		},
		/**
		 * Unbind - let's you unbind a variable from localStorage while removing the value from both
		 * the localStorage and the local variable and sets it to null
		 * @param $scope - the scope the variable was initially set in
		 * @param key - the name of the variable you are unbinding
		 */
		unbind: function($scope,key) {
			$parse(key).assign($scope, null);
			$scope.$watch(key, function () { });
			publicMethods.remove(key);
		}
	};
	return publicMethods;
});
<|endoftext|>


<commit_before>import btod from "./btod";
import formatDefault from "./formatDefault";
import formatGroup from "./formatGroup";
import formatRounded from "./formatRounded";
import formatRoundedPercentage from "./formatRoundedPercentage";
import formatSystem from "./formatSystem";

// [[fill]align][sign][symbol][0][width][,][.precision][type]
var formatRe = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;

var formatTypes = {
  "b": function(x) { return x.toString(2); },
  "c": function(x) { return String.fromCharCode(x); },
  "o": function(x) { return x.toString(8); },
  "x": function(x) { return x.toString(16); },
  "X": function(x) { return x.toString(16).toUpperCase(); },
  "g": function(x, p) { return x.toPrecision(p); },
  "e": function(x, p) { return x.toExponential(p); },
  "f": function(x, p) { return x.toFixed(p); },
  "%": function(x, p) { return (x * 100).toFixed(p); },
  "p": formatRoundedPercentage,
  "r": formatRounded,
  "s": formatSystem
};

function identity(x) {
  return x;
}

export default function(locale) {
  var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity,
      currency = locale.currency,
      decimal = locale.decimal;

  return function(specifier) {
    var match = formatRe.exec(specifier),
        fill = match[1] || " ",
        align = match[2] || ">",
        sign = match[3] || "-",
        symbol = match[4] || "",
        zero = match[5],
        width = +match[6],
        comma = match[7],
        precision = match[8],
        type = match[9] || "";

    // The "n" type is an alias for ",g".
    if (type === "n") comma = true, type = "g";

    // If zero fill is specified, padding goes after sign and before digits.
    if (zero || (fill === "0" && align === "=")) zero = fill = "0", align = "=";

    // Clamp the specified precision to the supported range.
    // For significant precision, it must be in [1, 21].
    // For fixed precision, it must be in [0, 20].
    if (precision) {
      precision = +precision.substring(1);
      precision = /[gprs]/.test(type)
          ? Math.max(1, Math.min(21, precision))
          : Math.max(0, Math.min(20, precision));
    }

    // Compute the fixed prefix and suffix.
    var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
        suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";

    // Is this an integer type?
    // Can this type generate exponential notation?
    // What format function should we use?
    var integer = /[bcdoxX]/.test(type),
        maybeDecimal = !type || /[defgprs%]/.test(type),
        maybeExponent = !type || /[deg]/.test(type),
        format = formatTypes[type] || formatDefault;

    return function(value) {
      value = +value;

      // Return the empty string for floats formatted as ints.
      if (integer && (value % 1)) return "";

      // Convert negative to positive, and record the sign.
      // Note that -0 is not less than 0, but 1 / -0 is!
      var valueSign = value < 0 || 1 / value < 0 ? (value *= -1, "-")
          : sign === "-" ? ""
          : sign;

      // Perform the initial formatting.
      var before = value = format(value, precision),
          after = suffix;

      // Break the value into the integer “before” part that can be grouped,
      // and fractional and exponential “after” part that is not grouped.
      if (maybeDecimal) {
        var i = value.indexOf(".");
        if (i < 0) {
          if (maybeExponent) {
            var j = value.indexOf("e");
            if (j >= 0) {
              before = value.substring(0, j);
              after = value.substring(j) + suffix;
            }
          }
        } else {
          before = value.substring(0, i);
          after = decimal + value.substring(i + 1) + suffix;
        }
      }

      // If the fill character is not "0", grouping is applied before padding.
      if (comma && !zero) before = group(before, Infinity);

      // Compute the padding.
      var length = (comma && zero ? 0 : valueSign.length) + prefix.length + before.length + after.length,
          padding = length < width ? new Array(length = width - length + 1).join(fill) : "";

      // If the fill character is "0", grouping is applied after padding.
      if (comma && zero) before = group(padding + before, padding.length ? width - after.length : Infinity), padding = "";

      // Reconstruct the final output based on the desired alignment.
      return align === "<" ? valueSign + prefix + before + after + padding
          : align === ">" ? padding + valueSign + prefix + before + after
          : align === "^" ? padding.substring(0, length >>= 1) + valueSign + prefix + before + after + padding.substring(length)
          : valueSign + prefix + padding + before + after;
    };
  };
};
<commit_msg>Cleaner.<commit_after>import btod from "./btod";
import formatDefault from "./formatDefault";
import formatGroup from "./formatGroup";
import formatRounded from "./formatRounded";
import formatRoundedPercentage from "./formatRoundedPercentage";
import formatSystem from "./formatSystem";

// [[fill]align][sign][symbol][0][width][,][.precision][type]
var formatRe = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;

var formatTypes = {
  "b": function(x) { return x.toString(2); },
  "c": function(x) { return String.fromCharCode(x); },
  "o": function(x) { return x.toString(8); },
  "x": function(x) { return x.toString(16); },
  "X": function(x) { return x.toString(16).toUpperCase(); },
  "g": function(x, p) { return x.toPrecision(p); },
  "e": function(x, p) { return x.toExponential(p); },
  "f": function(x, p) { return x.toFixed(p); },
  "%": function(x, p) { return (x * 100).toFixed(p); },
  "p": formatRoundedPercentage,
  "r": formatRounded,
  "s": formatSystem
};

function identity(x) {
  return x;
}

export default function(locale) {
  var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity,
      currency = locale.currency,
      decimal = locale.decimal;

  return function(specifier) {
    var match = formatRe.exec(specifier),
        fill = match[1] || " ",
        align = match[2] || ">",
        sign = match[3] || "-",
        symbol = match[4] || "",
        zero = match[5],
        width = +match[6],
        comma = match[7],
        precision = match[8],
        type = match[9] || "";

    // The "n" type is an alias for ",g".
    if (type === "n") comma = true, type = "g";

    // If zero fill is specified, padding goes after sign and before digits.
    if (zero || (fill === "0" && align === "=")) zero = fill = "0", align = "=";

    // Clamp the specified precision to the supported range.
    // For significant precision, it must be in [1, 21].
    // For fixed precision, it must be in [0, 20].
    if (precision) {
      precision = +precision.substring(1);
      precision = /[gprs]/.test(type)
          ? Math.max(1, Math.min(21, precision))
          : Math.max(0, Math.min(20, precision));
    }

    // Compute the fixed prefix and suffix.
    var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
        suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";

    // Is this an integer type?
    // Can this type generate exponential notation?
    // What format function should we use?
    var integer = /[bcdoxX]/.test(type),
        maybeDecimal = !type || /[defgprs%]/.test(type),
        maybeExponent = !type || /[deg]/.test(type),
        format = formatTypes[type] || formatDefault;

    return function(value) {
      value = +value;

      // Return the empty string for floats formatted as ints.
      if (integer && (value % 1)) return "";

      // Convert negative to positive, and record the sign.
      // Note that -0 is not less than 0, but 1 / -0 is!
      var valueSign = value < 0 || 1 / value < 0 ? (value *= -1, "-")
          : sign === "-" ? ""
          : sign;

      // Perform the initial formatting.
      var before = value = format(value, precision),
          after = suffix;

      // Break the value into the integer “before” part that can be grouped,
      // and fractional and exponential “after” part that is not grouped.
      if (maybeDecimal) {
        var i = value.indexOf(".");
        if (i < 0) {
          if (maybeExponent) {
            var j = value.indexOf("e");
            if (j >= 0) {
              before = value.substring(0, j);
              after = value.substring(j) + suffix;
            }
          }
        } else {
          before = value.substring(0, i);
          after = decimal + value.substring(i + 1) + suffix;
        }
      }

      // If the fill character is not "0", grouping is applied before padding.
      if (comma && !zero) before = group(before, Infinity);

      // Compute the padding.
      var length = (comma && zero ? 0 : valueSign.length) + prefix.length + before.length + after.length,
          padding = length < width ? new Array(length = width - length + 1).join(fill) : "";

      // If the fill character is "0", grouping is applied after padding.
      if (comma && zero) before = group(padding + before, padding.length ? width - after.length : Infinity), padding = "";

      // Reconstruct the final output based on the desired alignment.
      switch (align) {
        case "<": return valueSign + prefix + before + after + padding;
        case "=": return valueSign + prefix + padding + before + after;
        case "^": return padding.substring(0, length >>= 1) + valueSign + prefix + before + after + padding.substring(length);
        default: return padding + valueSign + prefix + before + after;
      }
    };
  };
};
<|endoftext|>


<commit_before>import HeroModule from './hero'
import HeroController from './hero.controller';
import HeroComponent from './hero.component';
import HeroTemplate from './hero.html';

describe('Hero', ()=>{
	let $rootScope,
	makeController;

	beforeEach(window.module(HeroModule.name));
	beforeEach(inject((_$rootScope_)=>{
		$rootScope = _$rootScope_;
		makeController = ()=>{
			return new HeroController();
		};
	}));

	describe('Module', ()=>{
		// test things about the component module
		// checking to see if it registers certain things and what not
		// test for best practices with naming too
		// test for routing
	});

	describe('Controller', ()=>{
		// test your controller here

		it('should have a name property [REMOVE]', ()=>{ // erase me if you remove this.name from the controller
			let controller = makeController();

			expect(controller).to.have.property('name');
		});
	});

	describe('Template', ()=>{
		// test the template
		// use Regexes to test that you are using the right bindings {{  }}

		it('should have name in template [REMOVE]', ()=>{
			expect(HeroTemplate).to.match(/{{\s?vm\.name\s?}}/g);
		});
	});

	describe('Component', ()=>{
			// test the component/directive itself
			let component = HeroComponent();

			it('should use the right template',()=>{
				expect(component.template).to.equal(HeroTemplate);
			});

			it('should use controllerAs', ()=>{
				expect(component).to.have.property('controllerAs');
			});

			it('should use the right controller', ()=>{
				expect(component.controller).to.equal(HeroController);
			});
	});
});

<commit_msg>Update hero.spec.js<commit_after>import HeroModule from './hero'
import HeroController from './hero.controller';
import HeroComponent from './hero.component';
import HeroTemplate from './hero.html';

describe('Hero', () => {
  let $rootScope, makeController;

  beforeEach(window.module(HeroModule.name));
  beforeEach(inject((_$rootScope_) => {
    $rootScope = _$rootScope_;
    makeController = () => {
      return new HeroController();
    };
  }));

  describe('Module', () => {
    // top-level specs: i.e., routes, injection, naming
  });

  describe('Controller', () => {
    // controller specs
    it('has a name property [REMOVE]', () => { // erase if removing this.name from the controller
      let controller = makeController();
      expect(controller).to.have.property('name');
    });
  });

  describe('Template', () => {
    // template specs
    // tip: use regex to ensure correct bindings are used e.g., {{  }}
    it('has name in template [REMOVE]', () => {
      expect(HeroTemplate).to.match(/{{\s?vm\.name\s?}}/g);
    });
  });

  describe('Component', () => {
      // component/directive specs
      let component = HeroComponent();

      it('includes the intended template',() => {
        expect(component.template).to.equal(HeroTemplate);
      });

      it('uses `controllerAs` syntax', () => {
        expect(component).to.have.property('controllerAs');
      });

      it('invokes the right controller', () => {
        expect(component.controller).to.equal(HeroController);
      });
  });
});
<|endoftext|>