<commit_before>var _ = require('lodash'),
    sdk = require('postman-collection'),

    createAuthInterface = require('./auth-interface'),

    AUTH_TYPE_PROP = '__auth_type',

    AuthLoader,
    authorizeRequest;

/**
 * This object manages loading and finding Handlers for auth.
 *
 * @type AuthLoader
 */
AuthLoader = {
    /**
     * Houses list of available Authentication handlers.
     *
     * @property
     */
    handlers: {},

    /**
     * Finds the Handler for an Auth type.
     *
     * @param name
     *
     * @returns {AuthHandler}
     */
    getHandler: function (name) {
        return AuthLoader.handlers[name];
    },

    /**
     * Adds a Handler for use with given Auth type.
     *
     * @param Handler
     * @param name
     */
    addHandler: function (Handler, name) {
        if (!_.isFunction(Handler.init)) {
            throw new Error('The handler for "' + name + '" does not have an "init" function, which is necessary');
        }

        if (!_.isFunction(Handler.pre)) {
            throw new Error('The handler for "' + name + '" does not have a "pre" function, which is necessary');
        }

        if (!_.isFunction(Handler.post)) {
            throw new Error('The handler for "' + name + '" does not have a "post" function, which is necessary');
        }

        if (!_.isFunction(Handler.sign)) {
            throw new Error('The handler for "' + name + '" does not have a "sign" function, which is necessary');
        }

        Object.defineProperty(Handler, AUTH_TYPE_PROP, {
            value: name,
            configurable: false,
            enumerable: false,
            writable: false
        });

        AuthLoader.handlers[name] = Handler;
    },

    /**
     * Removes the Handler for the Auth type.
     *
     * @param name
     */
    removeHandler: function (name) {
        AuthLoader.handlers[name] && (delete AuthLoader.handlers[name]);
    }
};

// Create a Handler from each Signer that the SDK provides. Basically, we augment the signers with extra
// helper functions which take over the job of preparing a request for signing.
_.forEach({
    noauth: require('./noauth'),
    awsv4: require('./aws4'),
    basic: require('./basic'),
    digest: require('./digest'),
    hawk: require('./hawk'),
    oauth1: require('./oauth1'),
    oauth2: require('./oauth2'),
    ntlm: require('./ntlm')
}, AuthLoader.addHandler);

/**
 * Creates a copy of request, with the appropriate auth headers or parameters added.
 *
 * @note This function does not take care of resolving variables.
 *
 * @param {Request} request
 * @param done
 *
 * @returns {Request}
 */
authorizeRequest = function (request, done) {
    if (!request.auth) {
        return done();
    }

    var clonedReq = new sdk.Request(request.toJSON()),
        auth = clonedReq.auth,
        authInterface = createAuthInterface(auth),
        handler = AuthLoader.getHandler(auth.type);

    if (handler) {
        handler.sign(authInterface, clonedReq, function () { return done(null, clonedReq); });
    }
    else {
        return done(new Error('runtime~authorizeRequest: could not find handler for auth type ' + auth.type));
    }
};

module.exports = {
    AuthLoader: AuthLoader,
    authorizeRequest: authorizeRequest
};
<commit_msg>Documents the AuthHandlerInterface's 4 hooks and 4 callback functions<commit_after>var _ = require('lodash'),
    sdk = require('postman-collection'),

    createAuthInterface = require('./auth-interface'),

    AUTH_TYPE_PROP = '__auth_type',

    AuthLoader,
    authorizeRequest;

/**
 * This object manages loading and finding Handlers for auth.
 *
 * @type AuthLoader
 */
AuthLoader = {
    /**
     * Houses list of available Authentication handlers.
     *
     * @property {Object}
     */
    handlers: {},

    /**
     * Finds the Handler for an Auth type.
     *
     * @param name
     *
     * @returns {AuthHandler}
     */
    getHandler: function (name) {
        return AuthLoader.handlers[name];
    },

    /**
     * Adds a Handler for use with given Auth type.
     *
     * @param Handler
     * @param name
     */
    addHandler: function (Handler, name) {
        if (!_.isFunction(Handler.init)) {
            throw new Error('The handler for "' + name + '" does not have an "init" function, which is necessary');
        }

        if (!_.isFunction(Handler.pre)) {
            throw new Error('The handler for "' + name + '" does not have a "pre" function, which is necessary');
        }

        if (!_.isFunction(Handler.post)) {
            throw new Error('The handler for "' + name + '" does not have a "post" function, which is necessary');
        }

        if (!_.isFunction(Handler.sign)) {
            throw new Error('The handler for "' + name + '" does not have a "sign" function, which is necessary');
        }

        Object.defineProperty(Handler, AUTH_TYPE_PROP, {
            value: name,
            configurable: false,
            enumerable: false,
            writable: false
        });

        AuthLoader.handlers[name] = Handler;
    },

    /**
     * Removes the Handler for the Auth type.
     *
     * @param name
     */
    removeHandler: function (name) {
        AuthLoader.handlers[name] && (delete AuthLoader.handlers[name]);
    }
};

// Create a Handler from each Signer that the SDK provides. Basically, we augment the signers with extra
// helper functions which take over the job of preparing a request for signing.
_.forEach({
    noauth: require('./noauth'),
    awsv4: require('./aws4'),
    basic: require('./basic'),
    digest: require('./digest'),
    hawk: require('./hawk'),
    oauth1: require('./oauth1'),
    oauth2: require('./oauth2'),
    ntlm: require('./ntlm')
}, AuthLoader.addHandler);

/**
 * Creates a copy of request, with the appropriate auth headers or parameters added.
 *
 * @note This function does not take care of resolving variables.
 *
 * @param {Request} request
 * @param done
 *
 * @returns {Request}
 */
authorizeRequest = function (request, done) {
    if (!request.auth) {
        return done();
    }

    var clonedReq = new sdk.Request(request.toJSON()),
        auth = clonedReq.auth,
        authInterface = createAuthInterface(auth),
        handler = AuthLoader.getHandler(auth.type);

    if (handler) {
        handler.sign(authInterface, clonedReq, function () { return done(null, clonedReq); });
    }
    else {
        return done(new Error('runtime~authorizeRequest: could not find handler for auth type ' + auth.type));
    }
};

module.exports = {
    AuthLoader: AuthLoader,
    authorizeRequest: authorizeRequest
};

// Interface
/**
 * Interface for implementing auth handlers
 *
 * @interface AuthHandlerInterface
 */

// Interface functions
/**
 * This hook decides whether all the required paramaters are present in the auth or not.
 * 3 things can happen depending on how it calls the [done]{@link authPreHookCallback} callback:
 *
 * 1. Calls with no error: Sign the request and proceed to send the request
 * 2. Calls with error but no request: don't sign the request, but proceed to send the request
 * 3. Calls with error and a request (for the possible formats see {@link authPreHookCallback}):
 *      - send the intermediate request
 *      - invoke the auth's [init]{@link AuthHandlerInterface#init} hook with the response of the intermediate request
 *      - invoke the auth's [pre]{@link AuthHandlerInterface#pre} hook
 *
 * @function
 * @name AuthHandlerInterface#pre
 *
 * @param {AuthInterface} auth
 * @param {authPreHookCallback} done Callback function which takes error, success, and request as arguments
 */

/**
 * This hook is called with the reponse from the intermediate request, which was requested from the
 * [pre]{@link AuthHandlerInterface#pre} hook.
 * Here the `auth` can be modified using the response. After this [pre]{@link AuthHandlerInterface#pre} hook will be
 * called again to verify the required paramaters.
 *
 * @function
 * @name AuthHandlerInterface#init
 *
 * @param {AuthInterface} auth
 * @param {Response} response
 * @param {authInitHookCallback} done Callback function which takes error as the only argument
 */

/**
 * This hook signs the `request` using the `auth`.
 *
 * @function
 * @name AuthHandlerInterface#sign
 *
 * @param {AuthInterface} auth
 * @param {Request} resquest
 * @param {authSignHookCallback} done Callback function which takes error as the only argument
 */

/**
 * This hook is called after the request is made. It receives the response using which it can determine whether
 * it was a failure or success. It can also modify the `auth` and ask to replay the `request`.
 * For this it has to call the [done]{@link authPostHookCallback} callback with `success` as false.
 *
 * @function
 * @name AuthHandlerInterface#post
 *
 * @param {AuthInterface} auth
 * @param {Response} response
 * @param {authPostHookCallback} done Callback function which takes error and success as arguments
 */

// Callbacks
/**
 * This callback is called in the `pre` hook of the auth handler
 * @callback authPreHookCallback
 * @param {Error|null} err
 * @param {Boolean} success
 * @param {object|string} request It can be either request URL or request definition
 */

/**
 * This callback is called in the `init` hook of the auth handler
 * @callback authInitHookCallback
 * @param {Error|null} error
 */

/**
 * This callback is called in the `sign` hook of the auth handler
 * @callback authSignHookCallback
 * @param {Error|null} err
 */

/**
 * This callback is called in the `post` hook of the auth handler
 * @callback authPostHookCallback
 * @param {Error|null} err
 * @param {Boolean} success
 */
<|endoftext|>


<commit_before>var dgram = require('dgram');

module.exports = function(settings) {
  var self = this;

  var messageHandler;
  var errorHandler;

  var server = dgram.createSocket('udp4');

  // Events
  server.on('message', function(msg, rinfo) {
    if (messageHandler) messageHandler(msg, rinfo.address);
  });

  server.on('error', function(err) {
    if (errorHandler) errorHandler(err);
  });

  // Public functions
  self.setMessageHandler = function(handler) {
    messageHandler = handler;
  };

  self.setErrorHandler = function(handler) {
    errorHandler = handler;
  };

  self.getBroadcastAddress = function() {
    return settings.broadcastAddress;
  };

  self.getMaxPayload = function() {
    return 1482;
  };

  self.send = function(buffer, offset, receiver) {
    server.send(buffer, 0, offset, settings.port, receiver);
  };

  self.open = function() {
    server.bind(settings.port, settings.interface, function() {
      server.setBroadcast(true);
    });
  };

  self.close = function() {
    server.close();
  };

  return self;
};
<commit_msg>feat(bacnet-transport): allow reuse of network interface when using bacstack<commit_after>var dgram = require('dgram');

module.exports = function(settings) {
  var self = this;

  var messageHandler;
  var errorHandler;

  var server = dgram.createSocket({type: 'udp4', reuseAddr: true});

  // Events
  server.on('message', function(msg, rinfo) {
    if (messageHandler) messageHandler(msg, rinfo.address);
  });

  server.on('error', function(err) {
    if (errorHandler) errorHandler(err);
  });

  // Public functions
  self.setMessageHandler = function(handler) {
    messageHandler = handler;
  };

  self.setErrorHandler = function(handler) {
    errorHandler = handler;
  };

  self.getBroadcastAddress = function() {
    return settings.broadcastAddress;
  };

  self.getMaxPayload = function() {
    return 1482;
  };

  self.send = function(buffer, offset, receiver) {
    server.send(buffer, 0, offset, settings.port, receiver);
  };

  self.open = function() {
    server.bind(settings.port, settings.interface, function() {
      server.setBroadcast(true);
    });
  };

  self.close = function() {
    server.close();
  };

  return self;
};
<|endoftext|>


<commit_before>module.exports = function(opts) {
  require('insert-css')('.bespoke-parent.bespoke-overview{pointer-events:auto}' +
    '.bespoke-overview :not(img){pointer-events:none}' +
    '.bespoke-overview .bespoke-slide{opacity:1;visibility:visible;cursor:pointer;pointer-events:auto}' +
    '.bespoke-overview .bespoke-active{outline:6px solid #cfd8dc;outline-offset:-3px;-moz-outline-radius:3px}' +
    '.bespoke-overview .bespoke-bullet{opacity:1;visibility:visible}' +
    '.bespoke-overview-counter{counter-reset:overview}' +
    '.bespoke-overview-counter .bespoke-slide::after{counter-increment:overview;content:counter(overview);position:absolute;right:.75em;bottom:.5em;font-size:1.25rem;line-height:1.25}' +
    '.bespoke-title{visibility:hidden;position:absolute;top:0;left:0;width:100%;pointer-events:auto}' +
    '.bespoke-title h1{margin:0;font-size:1.6em;line-height:1.2;text-align:center}' +
    '.bespoke-overview:not(.bespoke-overview-to) .bespoke-title{visibility:visible}' +
    '.bespoke-overview-to .bespoke-active,.bespoke-overview-from .bespoke-active{z-index:1}', { prepend: true });
  return function(deck) {
    opts = typeof opts === 'object' ? opts : {};
    var KEY_O = 79, KEY_ENT = 13, KEY_UP = 38, KEY_DN = 40,
      RE_CSV = /, */, RE_NONE = /^none(?:, ?none)*$/, RE_TRANS = /^translate\((.+?)px, ?(.+?)px\) scale\((.+?)\)$/, RE_MODE = /(^\?|&)overview(?=$|&)/,
      TRANSITIONEND = !('transition' in document.body.style) && ('webkitTransition' in document.body.style) ? 'webkitTransitionEnd' : 'transitionend',
      VENDOR = ['webkit', 'Moz'],
      columns = typeof opts.columns === 'number' ? parseInt(opts.columns) : 3,
      margin = typeof opts.margin === 'number' ? parseFloat(opts.margin) : 15,
      overviewActive = null,
      afterTransition,
      getStyleProperty = function(element, name) {
        if (!(name in element.style)) {
          var properName = name.charAt(0).toUpperCase() + name.substr(1);
          for (var i = 0, len = VENDOR.length; i < len; i++) {
            if (VENDOR[i] + properName in element.style) return VENDOR[i] + properName;
          }
        }
        return name;
      },
      getTransformScaleFactor = function(element, transformProp) {
        return parseFloat(element.style[transformProp].slice(6, -1));
      },
      getZoomFactor = function(element) {
        if ('zoom' in element.style) return parseFloat(element.style.zoom) || undefined;
      },
      getTransitionProperties = function(element) {
        var result = [],
          style = getComputedStyle(element),
          transitionProperty = style[getStyleProperty(element, 'transitionProperty')];
        if (!transitionProperty || RE_NONE.test(transitionProperty)) return result;
        // NOTE beyond this point, assume computed style returns compliant values
        transitionProperty = transitionProperty.split(RE_CSV);
        var transitionDuration = style[getStyleProperty(element, 'transitionDuration')].split(RE_CSV),
          transitionDelay = style[getStyleProperty(element, 'transitionDelay')].split(RE_CSV);
        transitionProperty.forEach(function(property, i) {
          if (transitionDuration[i] !== '0s' || transitionDelay[i] !== '0s') result.push(property);
        });
        return result;
      },
      flushStyle = function(element, property, from, to) {
        if (property) element.style[property] = from;
        element.offsetHeight; // jshint ignore: line
        if (property) element.style[property] = to;
      },
      onReady = function() {
        deck.on('activate', onReady)(); // unregisters listener
        deck.parent.scrollLeft = deck.parent.scrollTop = 0;
        if (!!opts.autostart || RE_MODE.test(location.search)) setTimeout(openOverview, 100); // timeout allows transitions to prepare
      },
      onSlideClick = function() {
        closeOverview(deck.slides.indexOf(this));
      },
      onNavigate = function(offset, e) {
        var targetIndex = e.index + offset;
        // IMPORTANT must use deck.slide to navigate and return false in order to circumvent bespoke-bullets behavior
        if (targetIndex >= 0 && targetIndex < deck.slides.length) deck.slide(targetIndex, { preview: true });
        return false;
      },
      onActivate = function(e) {
        if (e.scrollIntoView !== false) scrollSlideIntoView(e.slide, e.index, getZoomFactor(e.slide));
      },
      updateLocation = function(state) {
        var s = location.search.replace(RE_MODE, '').replace(/^[^?]/, '?$&');
        if (state) {
          history.replaceState(null, null, location.pathname + (s.length > 0 ? s + '&' : '?') + 'overview' + location.hash);
        }
        else {
          history.replaceState(null, null, location.pathname + s + location.hash);
        }
      },
      scrollSlideIntoView = function(slide, index, zoomFactor) {
        deck.parent.scrollTop = index < columns ? 0 : deck.parent.scrollTop + slide.getBoundingClientRect().top * (zoomFactor || 1);
      },
      removeAfterTransition = function(direction, parentClasses, slide, slideAlt) {
        slide.removeEventListener(TRANSITIONEND, afterTransition, false);
        if (slideAlt && slideAlt !== slide) slideAlt.removeEventListener(TRANSITIONEND, afterTransition, false);
        afterTransition = undefined;
        parentClasses.remove('bespoke-overview-' + direction);
      },
      getOrCreateTitle = function(parent) {
        var first = parent.firstElementChild;
        if (first.classList.contains('bespoke-title')) {
          first.style.width = '';
          return first;
        }
        var header = document.createElement('header');
        header.className = 'bespoke-title';
        header.style[getStyleProperty(header, 'transformOrigin')] = '0 0';
        var h1 = document.createElement('h1');
        h1.appendChild(document.createTextNode(parent.getAttribute('data-title') || document.title));
        header.appendChild(h1);
        flushStyle(parent.insertBefore(header, first));
        return header;
      },
      openOverview = function() {
        var slides = deck.slides,
          parent = deck.parent,
          parentClasses = parent.classList,
          lastSlideIndex = slides.length - 1,
          activeSlideIndex = deck.slide(),
          sampleSlide = activeSlideIndex > 0 ? slides[0] : slides[lastSlideIndex],
          transformProp = getStyleProperty(sampleSlide, 'transform'),
          scaleParent = parent.querySelector('.bespoke-scale-parent'),
          baseScale = 1,
          zoomFactor,
          title,
          numTransitions = 0,
          resize = overviewActive,
          isWebKit = 'webkitAppearance' in parent.style;
        if (scaleParent) {
          baseScale = getTransformScaleFactor(scaleParent, transformProp);
        }
        else if ((zoomFactor = getZoomFactor(sampleSlide))) {
          baseScale = zoomFactor;
        }
        if (afterTransition) removeAfterTransition('from', parentClasses, slides[0], slides[lastSlideIndex]);
        if (!!opts.title) title = getOrCreateTitle(parent);
        if (!resize) {
          deck.slide(activeSlideIndex, { preview: true });
          parentClasses.add('bespoke-overview');
          addEventListener('resize', openOverview, false);
          overviewActive = [deck.on('activate', onActivate), deck.on('prev', onNavigate.bind(null, -1)), deck.on('next', onNavigate.bind(null, 1))];
          if (!!opts.counter) parentClasses.add('bespoke-overview-counter');
          if (!!opts.location) updateLocation(true);
          parentClasses.add('bespoke-overview-to');
          numTransitions = lastSlideIndex > 0 ? getTransitionProperties(sampleSlide).length :
              (getTransitionProperties(sampleSlide).join(' ').indexOf('transform') < 0 ? 0 : 1);
          parent.style.overflowY = 'scroll'; // gives us fine-grained control
          parent.style.scrollBehavior = 'smooth'; // not supported by all browsers
          if (isWebKit) slides.forEach(function(slide) { flushStyle(slide, 'marginBottom', '0%', ''); });
        }
        var deckWidth = parent.clientWidth / baseScale,
          deckHeight = parent.clientHeight / baseScale,
          scrollbarWidth = (scaleParent || parent).offsetWidth - parent.clientWidth,
          scrollbarOffset = scaleParent ? scrollbarWidth / 2 / baseScale : 0,
          slideWidth = sampleSlide.offsetWidth,
          slideHeight = sampleSlide.offsetHeight,
          scale = deckWidth / (columns * slideWidth + (columns + 1) * margin),
          totalScale = baseScale * scale,
          scaledSlideWidth = slideWidth * scale,
          scaledSlideHeight = slideHeight * scale,
          // NOTE x & y offset calculation based on transform origin at center of slide
          slideX = (deckWidth - scaledSlideWidth) / 2,
          slideY = (deckHeight - scaledSlideHeight) / 2,
          scaledMargin = margin * scale,
          scaledTitleHeight = 0,
          row = 0, col = 0;
        if (title) {
          if (opts.scaleTitle !== false) {
            title.style[zoomFactor ? 'zoom' : transformProp] = zoomFactor ? totalScale : 'scale(' + totalScale + ')';
            title.style.width = (parent.clientWidth / totalScale) + 'px';
            scaledTitleHeight = title.offsetHeight * scale;
          }
          else {
            if (scrollbarWidth > 0) title.style.width = parent.clientWidth + 'px';
            scaledTitleHeight = title.offsetHeight / baseScale;
          }
        }
        slides.forEach(function(slide) {
          var x = col * scaledSlideWidth + (col + 1) * scaledMargin - scrollbarOffset - slideX,
            y = row * scaledSlideHeight + (row + 1) * scaledMargin + scaledTitleHeight - slideY;
          // NOTE drop scientific notation for numbers near 0 as it confuses WebKit
          slide.style[transformProp] = 'translate(' + (x.toString().indexOf('e-') < 0 ? x : 0) + 'px, ' +
              (y.toString().indexOf('e-') < 0 ? y : 0) + 'px) scale(' + scale + ')';
          // NOTE add margin to last slide to leave gap below last row; only honored by WebKit
          if (row * columns + col === lastSlideIndex) slide.style.marginBottom = margin + 'px';
          slide.addEventListener('click', onSlideClick, false);
          if (col === (columns - 1)) {
            row += 1;
            col = 0;
          }
          else {
            col += 1;
          }
        });
        if (resize) {
          scrollSlideIntoView(slides[activeSlideIndex], activeSlideIndex, zoomFactor);
        }
        else if (numTransitions > 0) {
          sampleSlide.addEventListener(TRANSITIONEND, (afterTransition = function(e) {
            if (e.target === this && (numTransitions -= 1) === 0) {
              removeAfterTransition('to', parentClasses, this);
              if (isWebKit && parent.scrollHeight > parent.clientHeight) {
                flushStyle(parent, 'overflowY', 'auto', 'scroll'); // awakens scrollbar from zombie state
              }
              scrollSlideIntoView(slides[activeSlideIndex], activeSlideIndex, zoomFactor);
            }
          }), false);
        }
        else {
          slides.forEach(function(slide) { flushStyle(slide); }); // bypass transition, if any
          parentClasses.remove('bespoke-overview-to');
          scrollSlideIntoView(slides[activeSlideIndex], activeSlideIndex, zoomFactor);
        }
      },
      // NOTE the order of operation in this method is critical; heavily impacts behavior & transition smoothness
      closeOverview = function(selection) {
        // IMPORTANT intentionally reselect active slide to reactivate behavior
        deck.slide(typeof selection === 'number' ? selection : deck.slide(), { scrollIntoView: false });
        var slides = deck.slides,
          parent = deck.parent,
          parentClasses = parent.classList,
          lastSlideIndex = slides.length - 1,
          sampleSlide = deck.slide() > 0 ? slides[0] : slides[lastSlideIndex],
          transformProp = getStyleProperty(sampleSlide, 'transform'),
          transitionProp = getStyleProperty(sampleSlide, 'transition'),
          scaleParent = parent.querySelector('.bespoke-scale-parent'),
          baseScale,
          isWebKit = 'webkitAppearance' in parent.style;
        if (scaleParent) {
          baseScale = getTransformScaleFactor(scaleParent, transformProp);
        }
        else if (!(baseScale = getZoomFactor(sampleSlide))) {
          baseScale = 1;
        }
        if (afterTransition) removeAfterTransition('to', parentClasses, slides[0], slides[lastSlideIndex]);
        var yShift = parent.scrollTop / baseScale,
          // xShift accounts for horizontal shift when scrollbar is removed
          xShift = (parent.offsetWidth - (scaleParent || parent).clientWidth) / 2 / baseScale;
        parent.style.scrollBehavior = parent.style.overflowY = '';
        slides.forEach(function(slide) {
          if (isWebKit) flushStyle(slide, 'marginBottom', '0%', '');
          slide.removeEventListener('click', onSlideClick, false);
        });
        if (yShift || xShift) {
          slides.forEach(function(slide) {
            var m = slide.style[transformProp].match(RE_TRANS);
            slide.style[transformProp] = 'translate(' + (parseFloat(m[1]) - xShift) + 'px, ' + (parseFloat(m[2]) - yShift) + 'px) scale(' + m[3] + ')';
            flushStyle(slide, transitionProp, 'none', ''); // bypass transition, if any
          });
        }
        parent.scrollTop = 0;
        parentClasses.remove('bespoke-overview');
        removeEventListener('resize', openOverview, false);
        (overviewActive || []).forEach(function(unbindEvent) { unbindEvent(); });
        overviewActive = null;
        if (!!opts.counter) parentClasses.remove('bespoke-overview-counter');
        if (!!opts.location) updateLocation(false);
        parentClasses.add('bespoke-overview-from');
        var numTransitions = lastSlideIndex > 0 ? getTransitionProperties(sampleSlide).length :
            (getTransitionProperties(sampleSlide).join(' ').indexOf('transform') < 0 ? 0 : 1);
        slides.forEach(function(slide) { slide.style[transformProp] = ''; });
        if (numTransitions > 0) {
          sampleSlide.addEventListener(TRANSITIONEND, (afterTransition = function(e) {
            if (e.target === this && (numTransitions -= 1) === 0) removeAfterTransition('from', parentClasses, this);
          }), false);
        }
        else {
          slides.forEach(function(slide) { flushStyle(slide); }); // bypass transition, if any
          parentClasses.remove('bespoke-overview-from');
        }
      },
      toggleOverview = function() {
        (overviewActive ? closeOverview : openOverview)();
      },
      onKeydown = function(e) {
        if (e.which === KEY_O) {
          if (!e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey) toggleOverview();
        }
        else if (overviewActive) {
          switch (e.which) {
            case KEY_ENT:
              if (!e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey) closeOverview();
              break;
            case KEY_UP:
              return onNavigate(-columns, { index: deck.slide() });
            case KEY_DN:
              return onNavigate(columns, { index: deck.slide() });
          }
        }
      };
    deck.on('activate', onReady);
    deck.on('destroy', function() {
      removeEventListener('resize', openOverview, false);
      document.removeEventListener('keydown', onKeydown, false);
    });
    deck.on('overview', toggleOverview);
    document.addEventListener('keydown', onKeydown, false);
  };
};
<commit_msg>reword comment<commit_after>module.exports = function(opts) {
  require('insert-css')('.bespoke-parent.bespoke-overview{pointer-events:auto}' +
    '.bespoke-overview :not(img){pointer-events:none}' +
    '.bespoke-overview .bespoke-slide{opacity:1;visibility:visible;cursor:pointer;pointer-events:auto}' +
    '.bespoke-overview .bespoke-active{outline:6px solid #cfd8dc;outline-offset:-3px;-moz-outline-radius:3px}' +
    '.bespoke-overview .bespoke-bullet{opacity:1;visibility:visible}' +
    '.bespoke-overview-counter{counter-reset:overview}' +
    '.bespoke-overview-counter .bespoke-slide::after{counter-increment:overview;content:counter(overview);position:absolute;right:.75em;bottom:.5em;font-size:1.25rem;line-height:1.25}' +
    '.bespoke-title{visibility:hidden;position:absolute;top:0;left:0;width:100%;pointer-events:auto}' +
    '.bespoke-title h1{margin:0;font-size:1.6em;line-height:1.2;text-align:center}' +
    '.bespoke-overview:not(.bespoke-overview-to) .bespoke-title{visibility:visible}' +
    '.bespoke-overview-to .bespoke-active,.bespoke-overview-from .bespoke-active{z-index:1}', { prepend: true });
  return function(deck) {
    opts = typeof opts === 'object' ? opts : {};
    var KEY_O = 79, KEY_ENT = 13, KEY_UP = 38, KEY_DN = 40,
      RE_CSV = /, */, RE_NONE = /^none(?:, ?none)*$/, RE_TRANS = /^translate\((.+?)px, ?(.+?)px\) scale\((.+?)\)$/, RE_MODE = /(^\?|&)overview(?=$|&)/,
      TRANSITIONEND = !('transition' in document.body.style) && ('webkitTransition' in document.body.style) ? 'webkitTransitionEnd' : 'transitionend',
      VENDOR = ['webkit', 'Moz'],
      columns = typeof opts.columns === 'number' ? parseInt(opts.columns) : 3,
      margin = typeof opts.margin === 'number' ? parseFloat(opts.margin) : 15,
      overviewActive = null,
      afterTransition,
      getStyleProperty = function(element, name) {
        if (!(name in element.style)) {
          var properName = name.charAt(0).toUpperCase() + name.substr(1);
          for (var i = 0, len = VENDOR.length; i < len; i++) {
            if (VENDOR[i] + properName in element.style) return VENDOR[i] + properName;
          }
        }
        return name;
      },
      getTransformScaleFactor = function(element, transformProp) {
        return parseFloat(element.style[transformProp].slice(6, -1));
      },
      getZoomFactor = function(element) {
        if ('zoom' in element.style) return parseFloat(element.style.zoom) || undefined;
      },
      getTransitionProperties = function(element) {
        var result = [],
          style = getComputedStyle(element),
          transitionProperty = style[getStyleProperty(element, 'transitionProperty')];
        if (!transitionProperty || RE_NONE.test(transitionProperty)) return result;
        // NOTE assume computed style returns compliant values beyond this point
        transitionProperty = transitionProperty.split(RE_CSV);
        var transitionDuration = style[getStyleProperty(element, 'transitionDuration')].split(RE_CSV),
          transitionDelay = style[getStyleProperty(element, 'transitionDelay')].split(RE_CSV);
        transitionProperty.forEach(function(property, i) {
          if (transitionDuration[i] !== '0s' || transitionDelay[i] !== '0s') result.push(property);
        });
        return result;
      },
      flushStyle = function(element, property, from, to) {
        if (property) element.style[property] = from;
        element.offsetHeight; // jshint ignore: line
        if (property) element.style[property] = to;
      },
      onReady = function() {
        deck.on('activate', onReady)(); // unregisters listener
        deck.parent.scrollLeft = deck.parent.scrollTop = 0;
        if (!!opts.autostart || RE_MODE.test(location.search)) setTimeout(openOverview, 100); // timeout allows transitions to prepare
      },
      onSlideClick = function() {
        closeOverview(deck.slides.indexOf(this));
      },
      onNavigate = function(offset, e) {
        var targetIndex = e.index + offset;
        // IMPORTANT must use deck.slide to navigate and return false in order to circumvent bespoke-bullets behavior
        if (targetIndex >= 0 && targetIndex < deck.slides.length) deck.slide(targetIndex, { preview: true });
        return false;
      },
      onActivate = function(e) {
        if (e.scrollIntoView !== false) scrollSlideIntoView(e.slide, e.index, getZoomFactor(e.slide));
      },
      updateLocation = function(state) {
        var s = location.search.replace(RE_MODE, '').replace(/^[^?]/, '?$&');
        if (state) {
          history.replaceState(null, null, location.pathname + (s.length > 0 ? s + '&' : '?') + 'overview' + location.hash);
        }
        else {
          history.replaceState(null, null, location.pathname + s + location.hash);
        }
      },
      scrollSlideIntoView = function(slide, index, zoomFactor) {
        deck.parent.scrollTop = index < columns ? 0 : deck.parent.scrollTop + slide.getBoundingClientRect().top * (zoomFactor || 1);
      },
      removeAfterTransition = function(direction, parentClasses, slide, slideAlt) {
        slide.removeEventListener(TRANSITIONEND, afterTransition, false);
        if (slideAlt && slideAlt !== slide) slideAlt.removeEventListener(TRANSITIONEND, afterTransition, false);
        afterTransition = undefined;
        parentClasses.remove('bespoke-overview-' + direction);
      },
      getOrCreateTitle = function(parent) {
        var first = parent.firstElementChild;
        if (first.classList.contains('bespoke-title')) {
          first.style.width = '';
          return first;
        }
        var header = document.createElement('header');
        header.className = 'bespoke-title';
        header.style[getStyleProperty(header, 'transformOrigin')] = '0 0';
        var h1 = document.createElement('h1');
        h1.appendChild(document.createTextNode(parent.getAttribute('data-title') || document.title));
        header.appendChild(h1);
        flushStyle(parent.insertBefore(header, first));
        return header;
      },
      openOverview = function() {
        var slides = deck.slides,
          parent = deck.parent,
          parentClasses = parent.classList,
          lastSlideIndex = slides.length - 1,
          activeSlideIndex = deck.slide(),
          sampleSlide = activeSlideIndex > 0 ? slides[0] : slides[lastSlideIndex],
          transformProp = getStyleProperty(sampleSlide, 'transform'),
          scaleParent = parent.querySelector('.bespoke-scale-parent'),
          baseScale = 1,
          zoomFactor,
          title,
          numTransitions = 0,
          resize = overviewActive,
          isWebKit = 'webkitAppearance' in parent.style;
        if (scaleParent) {
          baseScale = getTransformScaleFactor(scaleParent, transformProp);
        }
        else if ((zoomFactor = getZoomFactor(sampleSlide))) {
          baseScale = zoomFactor;
        }
        if (afterTransition) removeAfterTransition('from', parentClasses, slides[0], slides[lastSlideIndex]);
        if (!!opts.title) title = getOrCreateTitle(parent);
        if (!resize) {
          deck.slide(activeSlideIndex, { preview: true });
          parentClasses.add('bespoke-overview');
          addEventListener('resize', openOverview, false);
          overviewActive = [deck.on('activate', onActivate), deck.on('prev', onNavigate.bind(null, -1)), deck.on('next', onNavigate.bind(null, 1))];
          if (!!opts.counter) parentClasses.add('bespoke-overview-counter');
          if (!!opts.location) updateLocation(true);
          parentClasses.add('bespoke-overview-to');
          numTransitions = lastSlideIndex > 0 ? getTransitionProperties(sampleSlide).length :
              (getTransitionProperties(sampleSlide).join(' ').indexOf('transform') < 0 ? 0 : 1);
          parent.style.overflowY = 'scroll'; // gives us fine-grained control
          parent.style.scrollBehavior = 'smooth'; // not supported by all browsers
          if (isWebKit) slides.forEach(function(slide) { flushStyle(slide, 'marginBottom', '0%', ''); });
        }
        var deckWidth = parent.clientWidth / baseScale,
          deckHeight = parent.clientHeight / baseScale,
          scrollbarWidth = (scaleParent || parent).offsetWidth - parent.clientWidth,
          scrollbarOffset = scaleParent ? scrollbarWidth / 2 / baseScale : 0,
          slideWidth = sampleSlide.offsetWidth,
          slideHeight = sampleSlide.offsetHeight,
          scale = deckWidth / (columns * slideWidth + (columns + 1) * margin),
          totalScale = baseScale * scale,
          scaledSlideWidth = slideWidth * scale,
          scaledSlideHeight = slideHeight * scale,
          // NOTE x & y offset calculation based on transform origin at center of slide
          slideX = (deckWidth - scaledSlideWidth) / 2,
          slideY = (deckHeight - scaledSlideHeight) / 2,
          scaledMargin = margin * scale,
          scaledTitleHeight = 0,
          row = 0, col = 0;
        if (title) {
          if (opts.scaleTitle !== false) {
            title.style[zoomFactor ? 'zoom' : transformProp] = zoomFactor ? totalScale : 'scale(' + totalScale + ')';
            title.style.width = (parent.clientWidth / totalScale) + 'px';
            scaledTitleHeight = title.offsetHeight * scale;
          }
          else {
            if (scrollbarWidth > 0) title.style.width = parent.clientWidth + 'px';
            scaledTitleHeight = title.offsetHeight / baseScale;
          }
        }
        slides.forEach(function(slide) {
          var x = col * scaledSlideWidth + (col + 1) * scaledMargin - scrollbarOffset - slideX,
            y = row * scaledSlideHeight + (row + 1) * scaledMargin + scaledTitleHeight - slideY;
          // NOTE drop scientific notation for numbers near 0 as it confuses WebKit
          slide.style[transformProp] = 'translate(' + (x.toString().indexOf('e-') < 0 ? x : 0) + 'px, ' +
              (y.toString().indexOf('e-') < 0 ? y : 0) + 'px) scale(' + scale + ')';
          // NOTE add margin to last slide to leave gap below last row; only honored by WebKit
          if (row * columns + col === lastSlideIndex) slide.style.marginBottom = margin + 'px';
          slide.addEventListener('click', onSlideClick, false);
          if (col === (columns - 1)) {
            row += 1;
            col = 0;
          }
          else {
            col += 1;
          }
        });
        if (resize) {
          scrollSlideIntoView(slides[activeSlideIndex], activeSlideIndex, zoomFactor);
        }
        else if (numTransitions > 0) {
          sampleSlide.addEventListener(TRANSITIONEND, (afterTransition = function(e) {
            if (e.target === this && (numTransitions -= 1) === 0) {
              removeAfterTransition('to', parentClasses, this);
              if (isWebKit && parent.scrollHeight > parent.clientHeight) {
                flushStyle(parent, 'overflowY', 'auto', 'scroll'); // awakens scrollbar from zombie state
              }
              scrollSlideIntoView(slides[activeSlideIndex], activeSlideIndex, zoomFactor);
            }
          }), false);
        }
        else {
          slides.forEach(function(slide) { flushStyle(slide); }); // bypass transition, if any
          parentClasses.remove('bespoke-overview-to');
          scrollSlideIntoView(slides[activeSlideIndex], activeSlideIndex, zoomFactor);
        }
      },
      // NOTE the order of operation in this method is critical; heavily impacts behavior & transition smoothness
      closeOverview = function(selection) {
        // IMPORTANT intentionally reselect active slide to reactivate behavior
        deck.slide(typeof selection === 'number' ? selection : deck.slide(), { scrollIntoView: false });
        var slides = deck.slides,
          parent = deck.parent,
          parentClasses = parent.classList,
          lastSlideIndex = slides.length - 1,
          sampleSlide = deck.slide() > 0 ? slides[0] : slides[lastSlideIndex],
          transformProp = getStyleProperty(sampleSlide, 'transform'),
          transitionProp = getStyleProperty(sampleSlide, 'transition'),
          scaleParent = parent.querySelector('.bespoke-scale-parent'),
          baseScale,
          isWebKit = 'webkitAppearance' in parent.style;
        if (scaleParent) {
          baseScale = getTransformScaleFactor(scaleParent, transformProp);
        }
        else if (!(baseScale = getZoomFactor(sampleSlide))) {
          baseScale = 1;
        }
        if (afterTransition) removeAfterTransition('to', parentClasses, slides[0], slides[lastSlideIndex]);
        var yShift = parent.scrollTop / baseScale,
          // xShift accounts for horizontal shift when scrollbar is removed
          xShift = (parent.offsetWidth - (scaleParent || parent).clientWidth) / 2 / baseScale;
        parent.style.scrollBehavior = parent.style.overflowY = '';
        slides.forEach(function(slide) {
          if (isWebKit) flushStyle(slide, 'marginBottom', '0%', '');
          slide.removeEventListener('click', onSlideClick, false);
        });
        if (yShift || xShift) {
          slides.forEach(function(slide) {
            var m = slide.style[transformProp].match(RE_TRANS);
            slide.style[transformProp] = 'translate(' + (parseFloat(m[1]) - xShift) + 'px, ' + (parseFloat(m[2]) - yShift) + 'px) scale(' + m[3] + ')';
            flushStyle(slide, transitionProp, 'none', ''); // bypass transition, if any
          });
        }
        parent.scrollTop = 0;
        parentClasses.remove('bespoke-overview');
        removeEventListener('resize', openOverview, false);
        (overviewActive || []).forEach(function(unbindEvent) { unbindEvent(); });
        overviewActive = null;
        if (!!opts.counter) parentClasses.remove('bespoke-overview-counter');
        if (!!opts.location) updateLocation(false);
        parentClasses.add('bespoke-overview-from');
        var numTransitions = lastSlideIndex > 0 ? getTransitionProperties(sampleSlide).length :
            (getTransitionProperties(sampleSlide).join(' ').indexOf('transform') < 0 ? 0 : 1);
        slides.forEach(function(slide) { slide.style[transformProp] = ''; });
        if (numTransitions > 0) {
          sampleSlide.addEventListener(TRANSITIONEND, (afterTransition = function(e) {
            if (e.target === this && (numTransitions -= 1) === 0) removeAfterTransition('from', parentClasses, this);
          }), false);
        }
        else {
          slides.forEach(function(slide) { flushStyle(slide); }); // bypass transition, if any
          parentClasses.remove('bespoke-overview-from');
        }
      },
      toggleOverview = function() {
        (overviewActive ? closeOverview : openOverview)();
      },
      onKeydown = function(e) {
        if (e.which === KEY_O) {
          if (!e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey) toggleOverview();
        }
        else if (overviewActive) {
          switch (e.which) {
            case KEY_ENT:
              if (!e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey) closeOverview();
              break;
            case KEY_UP:
              return onNavigate(-columns, { index: deck.slide() });
            case KEY_DN:
              return onNavigate(columns, { index: deck.slide() });
          }
        }
      };
    deck.on('activate', onReady);
    deck.on('destroy', function() {
      removeEventListener('resize', openOverview, false);
      document.removeEventListener('keydown', onKeydown, false);
    });
    deck.on('overview', toggleOverview);
    document.addEventListener('keydown', onKeydown, false);
  };
};
<|endoftext|>


<commit_before>import { isArray } from 'lodash';
import findAll from './find-all';
import spliceString from './splice-string'

function applyFilter(method, string, ignore) {
    let newString = method(string);
    if (!isArray(ignore)) {
        return newString;
    }
    let newIgnore = ignore.map(element => method(element)),
        newMatches = findAll(newString, newIgnore),
        oldMatches = findAll(string, ignore);

    newMatches.forEach((element, i) => {
        let { match, index } = element;
        newString = spliceString(
            newString,
            index,
            match.length,
            oldMatches[i].match
        );
    });
    return newString;
}

export default applyFilter;<commit_msg>Update apply-filter.js<commit_after>import { isArray } from 'lodash';
import findAll from './find-all';
import spliceString from './splice-string'

function applyFilter(method, string, ignore) {
    let newString = method(string);
    if (!isArray(ignore) || !ignore.length) {
        return newString;
    }
    let newIgnore = ignore.map(element => method(element)),
        newMatches = findAll(newString, newIgnore),
        oldMatches = findAll(string, ignore);

    newMatches.forEach((element, i) => {
        let { match, index } = element;
        newString = spliceString(
            newString,
            index,
            match.length,
            oldMatches[i].match
        );
    });
    return newString;
}

export default applyFilter;
<|endoftext|>


<commit_before>const isServer = typeof window === "undefined";
const requestAnimationFrame = (function() {
    if (isServer) return;
    var raf = window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        function(fn) {
            return window.setTimeOut(fn, 20);
        };
    return function(fn) {
        return raf(fn)
    }
})();

const cancelAnimationFrame = (function() {
    if (isServer) return;
    var caf = window.cancelAnimationFrame ||
        window.mozCancelAnimationFrame ||
        window.webkitCancelAnimationFrame ||
        window.clearTimeout;
    return function(id) {
        return caf(id);
    }
})();

const resetTrigger = function(element) {
    const trigger = element._resetTrigger_;
    const expand = trigger.firstElementChild;
    const contract = trigger.lastElementChild;
    const expandChild = expand.firstElementChild;

    contract.scrollLeft = contract.scrollWidth;
    contract.scrollTop = contract.scrollHeight;
    expandChild.style.width = expand.offsetWidth + 1 + "px";
    expandChild.style.height = expand.offsetHeight + 1 + "px";
    expand.scrollLeft = expand.scrollWidth;
    expand.scrollTop = expand.scrollHeight;
};

const checkTrigger = function(element) {
    return element.offsetWidth !== element._resizeLast_.width || element._resizeLast_.height;
};
const scrollListener = function(event) {
    resetTrigger(this);
    if (this._resizeRAF_) cancelAnimationFrame(this._resizeRAF_);
    this._resizeRAF_ = requestAnimationFrame(() => {
        if (checkTrigger(this)) {
            this._resizeLast_.width = this.offsetWidth;
            this._resizeLast_.Height = this.offsetHeight;
            this._resizeListeners_.forEach((fn) => {
                fn.call(this, event);
            });
        }
    });
};
const attachEvent = isServer ? function() {} : document.attachEvent;
const DOM_PREFIXES = "webkit ms o moz".split(" ");
const START_EVENTS = "webkitAnimationStart animationStart oAnimationStart MSAnimationStart".split(" ");
const RESIZE_ANIMATION_NAME = "resizeAnim";
let animation = false;
let keyFramePrefix = "";
let animationStartEvent = "animationStartEvent";

if (!attachEvent && !isServer) {
    const testElement = document.createElement("fakeelement");
    if (testElement.style.animationName !== undefined) {
        animation = true;
    }
}
<commit_msg>fix resize-event<commit_after>const isServer = typeof window === "undefined";
const requestAnimationFrame = (function() {
    if (isServer) return;
    var raf = window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        function(fn) {
            return window.setTimeOut(fn, 20);
        };
    return function(fn) {
        return raf(fn)
    }
})();

const cancelAnimationFrame = (function() {
    if (isServer) return;
    var caf = window.cancelAnimationFrame ||
        window.mozCancelAnimationFrame ||
        window.webkitCancelAnimationFrame ||
        window.clearTimeout;
    return function(id) {
        return caf(id);
    }
})();

const resetTrigger = function(element) {
    const trigger = element._resetTrigger_;
    const expand = trigger.firstElementChild;
    const contract = trigger.lastElementChild;
    const expandChild = expand.firstElementChild;

    contract.scrollLeft = contract.scrollWidth;
    contract.scrollTop = contract.scrollHeight;
    expandChild.style.width = expand.offsetWidth + 1 + "px";
    expandChild.style.height = expand.offsetHeight + 1 + "px";
    expand.scrollLeft = expand.scrollWidth;
    expand.scrollTop = expand.scrollHeight;
};

const checkTrigger = function(element) {
    return element.offsetWidth !== element._resizeLast_.width || element._resizeLast_.height;
};
const scrollListener = function(event) {
    resetTrigger(this);
    if (this._resizeRAF_) cancelAnimationFrame(this._resizeRAF_);
    this._resizeRAF_ = requestAnimationFrame(() => {
        if (checkTrigger(this)) {
            this._resizeLast_.width = this.offsetWidth;
            this._resizeLast_.Height = this.offsetHeight;
            this._resizeListeners_.forEach((fn) => {
                fn.call(this, event);
            });
        }
    });
};
const attachEvent = isServer ? function() {} : document.attachEvent;
const DOM_PREFIXES = "webkit ms o moz".split(" ");
const START_EVENTS = "webkitAnimationStart animationStart oAnimationStart MSAnimationStart".split(" ");
const RESIZE_ANIMATION_NAME = "resizeAnim";
let animation = false;
let keyFramePrefix = "";
let animationStartEvent = "animationStartEvent";

if (!attachEvent && !isServer) {
    const testElement = document.createElement("fakeelement");
    if (testElement.style.animationName !== undefined) {
        animation = true;
    }
    if(animation===false){
        let prefix==='';
        for(var i=0,len=DOM_PREFIXES.length;i<len;i++){
            if(testElement.style[DOM_PREFIXES[i]+'AnimationName']!==undefined){

            }
        }
    }
}
<|endoftext|>


<commit_before>/**
 * @module
 * @export {Class} TouchRecord
 */

import { getPosition } from './get-position';

class Tracker {
    constructor(touch) {
        this.updateTime = Date.now();
        this.delta = { x: 0, y: 0 };
        this.velocity = { x: 0, y: 0 };
        this.lastPosition = getPosition(touch);
    }

    update(touch) {
        const {
            velocity,
            updateTime,
            lastPosition,
        } = this;

        const now = Date.now();
        const position = getPosition(touch);

        const delta = {
            x: -(position.x - lastPosition.x),
            y: -(position.y - lastPosition.y),
        };

        const duration = now - updateTime + 1;
        const vx = delta.x / duration * 1e3;
        const vy = delta.y / duration * 1e3;
        velocity.x = vx * 0.8 + velocity.x * 0.2;
        velocity.y = vy * 0.8 + velocity.y * 0.2;

        this.delta = delta;
        this.updateTime = now;
        this.lastPosition = position;
    }
}

export class TouchRecord {
    constructor() {
        this.touchList = {};
        this.lastTouch = null;
        this.activeTouchID = undefined;
    }

    get __primitiveValue() {
        return { x: 0, y: 0 };
    }

    __add(touch) {
        if (this.__has(touch)) return null;

        const tracker = new Tracker(touch);

        this.touchList[touch.identifier] = tracker;

        return tracker;
    }

    __renew(touch) {
        if (!this.__has(touch)) return null;

        const tracker = this.touchList[touch.identifier];

        tracker.update(touch);

        return tracker;
    }

    __delete(touch) {
        return delete this.touchList[touch.identifier];
    }

    __has(touch) {
        return this.touchList.hasOwnProperty(touch.identifier);
    }

    __setActiveID(touches) {
        this.activeTouchID = touches[touches.length - 1].identifier;
        this.lastTouch = this.touchList[this.activeTouchID];
    }

    __getActiveTracker() {
        const {
            touchList,
            activeTouchID,
        } = this;

        return touchList[activeTouchID];
    }

    isActive() {
        return this.activeTouchID !== undefined;
    }

    getDelta() {
        const tracker = this.__getActiveTracker();

        if (!tracker) {
            return this.__primitiveValue;
        }

        return { ...tracker.delta };
    }

    getVelocity() {
        const tracker = this.__getActiveTracker();

        if (!tracker) {
            return this.__primitiveValue;
        }

        return { ...tracker.velocity };
    }

    getLastPosition(coord = '') {
        const tracker = this.__getActiveTracker() || this.lastTouch;

        const position = tracker ? tracker.lastPosition : this.__primitiveValue;

        if (!coord) return { ...position };

        if (!position.hasOwnProperty(coord)) return 0;

        return position[coord];
    }

    updatedRecently() {
        const tracker = this.__getActiveTracker();

        return tracker && Date.now() - tracker.updateTime < 30;
    }

    track(evt) {
        const {
            targetTouches,
        } = evt;

        [...targetTouches].forEach(touch => {
            this.__add(touch);
        });

        this.__setActiveID(targetTouches);

        return this.touchList;
    }

    update(evt) {
        const {
            touches,
            changedTouches,
        } = evt;

        [...touches].forEach(touch => {
            this.__renew(touch);
        });

        if (this.activeTouchID === undefined) {
            this.__setActiveID(changedTouches);
        }

        return this.touchList;
    }

    release(evt) {
        this.activeTouchID = undefined;

        [...evt.changedTouches].forEach(touch => {
            this.__delete(touch);
        });

        return this.touchList;
    }
}
<commit_msg>fix(touchRecord): limit update duration >=16<commit_after>/**
 * @module
 * @export {Class} TouchRecord
 */

import { getPosition } from './get-position';

class Tracker {
    constructor(touch) {
        this.updateTime = Date.now();
        this.delta = { x: 0, y: 0 };
        this.velocity = { x: 0, y: 0 };
        this.lastPosition = getPosition(touch);
    }

    update(touch) {
        const {
            velocity,
            updateTime,
            lastPosition,
        } = this;

        const now = Date.now();
        const position = getPosition(touch);

        const delta = {
            x: -(position.x - lastPosition.x),
            y: -(position.y - lastPosition.y),
        };

        const duration = (now - updateTime) || 16;
        const vx = delta.x / duration * 1e3;
        const vy = delta.y / duration * 1e3;
        velocity.x = vx * 0.8 + velocity.x * 0.2;
        velocity.y = vy * 0.8 + velocity.y * 0.2;

        this.delta = delta;
        this.updateTime = now;
        this.lastPosition = position;
    }
}

export class TouchRecord {
    constructor() {
        this.touchList = {};
        this.lastTouch = null;
        this.activeTouchID = undefined;
    }

    get __primitiveValue() {
        return { x: 0, y: 0 };
    }

    __add(touch) {
        if (this.__has(touch)) return null;

        const tracker = new Tracker(touch);

        this.touchList[touch.identifier] = tracker;

        return tracker;
    }

    __renew(touch) {
        if (!this.__has(touch)) return null;

        const tracker = this.touchList[touch.identifier];

        tracker.update(touch);

        return tracker;
    }

    __delete(touch) {
        return delete this.touchList[touch.identifier];
    }

    __has(touch) {
        return this.touchList.hasOwnProperty(touch.identifier);
    }

    __setActiveID(touches) {
        this.activeTouchID = touches[touches.length - 1].identifier;
        this.lastTouch = this.touchList[this.activeTouchID];
    }

    __getActiveTracker() {
        const {
            touchList,
            activeTouchID,
        } = this;

        return touchList[activeTouchID];
    }

    isActive() {
        return this.activeTouchID !== undefined;
    }

    getDelta() {
        const tracker = this.__getActiveTracker();

        if (!tracker) {
            return this.__primitiveValue;
        }

        return { ...tracker.delta };
    }

    getVelocity() {
        const tracker = this.__getActiveTracker();

        if (!tracker) {
            return this.__primitiveValue;
        }

        return { ...tracker.velocity };
    }

    getLastPosition(coord = '') {
        const tracker = this.__getActiveTracker() || this.lastTouch;

        const position = tracker ? tracker.lastPosition : this.__primitiveValue;

        if (!coord) return { ...position };

        if (!position.hasOwnProperty(coord)) return 0;

        return position[coord];
    }

    updatedRecently() {
        const tracker = this.__getActiveTracker();

        return tracker && Date.now() - tracker.updateTime < 30;
    }

    track(evt) {
        const {
            targetTouches,
        } = evt;

        [...targetTouches].forEach(touch => {
            this.__add(touch);
        });

        this.__setActiveID(targetTouches);

        return this.touchList;
    }

    update(evt) {
        const {
            touches,
            changedTouches,
        } = evt;

        [...touches].forEach(touch => {
            this.__renew(touch);
        });

        if (this.activeTouchID === undefined) {
            this.__setActiveID(changedTouches);
        }

        return this.touchList;
    }

    release(evt) {
        this.activeTouchID = undefined;

        [...evt.changedTouches].forEach(touch => {
            this.__delete(touch);
        });

        return this.touchList;
    }
}
<|endoftext|>


<commit_before>import React, { Suspense } from "react";
import { Router, View } from "react-navi";
import { ThemeProvider } from "emotion-theming";
import { ColorModeProvider, useColorMode } from "@chakra-ui/core";
import { CSSReset } from "@chakra-ui/core";
import { ConfigProvider } from "./lib/hooks/config";
import routes from "./routes";
import theme from "./theme";
import config from "./config";

const App = () => {
  return (
    <Router routes={routes}>
      <ConfigProvider config={config}>
        <ThemeProvider theme={theme}>
          <CSSReset />
          <ColorModeProvider>
            <Suspense fallback={null}>
              <View />
            </Suspense>
          </ColorModeProvider>
        </ThemeProvider>
      </ConfigProvider>
    </Router>
  );
};

export default App;
<commit_msg>use helmet and store provider<commit_after>import React, { Suspense } from "react";
import { Router, View } from "react-navi";
import { ThemeProvider } from "emotion-theming";
import { ColorModeProvider, useColorMode } from "@chakra-ui/core";
import HelmetProvider from "react-navi-helmet-async";
import { CSSReset } from "@chakra-ui/core";
import { ConfigProvider } from "./lib/hooks/config";
import { StoreProvider } from "./lib/hooks/store";
import routes from "./routes";
import theme from "./theme";
import config from "./config";

const App = () => {
  return (
    <HelmetProvider>
      <Router routes={routes}>
        <ConfigProvider config={config}>
          <StoreProvider>
            <ThemeProvider theme={theme}>
              <CSSReset />
              <ColorModeProvider>
                <Suspense fallback={null}>
                  <View />
                </Suspense>
              </ColorModeProvider>
            </ThemeProvider>
          </StoreProvider>
        </ConfigProvider>
      </Router>
    </HelmetProvider>
  );
};

export default App;
<|endoftext|>


<commit_before>// GLOBAL //
const seed = Math.floor(Math.random() * 999 + 1);
let debugMode = true;
let gifMode = false;
let autoMode = false; // automatically calculate timescale

// MAP //
const mapSize = 150;
const tileSize = 250;
const selectSizeAddition = 40;

let maxTileFood = 100; // Maximum food in a tile
const foodRegrowRate = 0.025; // How fast food regrows

const waterBias = 0.4; // Becomes unstable above about 0.75
const distanceSmoothing = 0.5; // less land further away from center
const continentSize = 50; // How large the islands are (maintains water ratio)

const growSeasonLength = 800; // Grow season length
const dieSeasonLength = 1000; // Die season length

const seasonChange = 0.02; // Food grow speed change (added in grow season and subtracted in die season)
const mapUpdateDelay = 100;

// CREATURES //
const minCreatures = 50; // Minimum number of creatures
const minFirstGen = 10; // Minimum number of first generation creatures

const creatureEnergy = 80; // Max creature energy

const speciesDiversity = 6; // Diversity of each species
const speciesColorChange = 20; // Color change between species

const maxCreatureSize = 100; // Maximum Creature Size
const minCreatureSize = 30; // Minimum Creature Size

const maxCreatureSpeed = 30; // Maximum Creature Speed
const swimmingSpeed = 0.3; // Speed % in water
const agingSpeed = 0.2; // Aging speed percentage %
const eatingSpeed = 0.0; // Speed % while eating

const rotationSpeed = 0.1; // Speed % how fast creatures rotate

let oldest = 0; // oldest creature's age

const maxEyes = 2; // maximum number of "eyes" a creature can have
const maxEyeDistance = 500; // Maximum distance an "eye" can be from a creature

const energy = { // Energy cost per tick
    eat: 0.04, // Energy cost to eat
    metabolism: 0.04, // Energy cost to live
    move: 0.05, // Energy cost to move
    attack: 0.04, // Energy cost to attack
    birth: 1 // Energy cost to birth
};

const eatEffeciency = 0.9; // Eat effeciency %
const birthEffeciency = 0.85; // Birth effeciency %
const attackEffeciency = 2.00; // Attack effeciency %
const attackPower = 3.00; // Attack power %

const minEatPower = 0.0; // Minimum eating strength (anything lower will be 0)
const minReproducePower = 0.0; // Minimum output to reproduce (anything lower will be 0)
const minAttackPower = 0.0; // Minimum attack strength (anything lower will be 0)

const reproduceAge = 1200; // Minimum age when a creature can reproduce
const minReproduceTime = 800; // Minimum time between litters

// Neural Network //
const offset = 0.0; // Amount to offset the value of a neuron
const mutability = 4; // Chance of mutating a single axon

const minStepAmount = Number.EPSILON; // Min step amount (Number.EPSILON is the smallest positive number)
const stepAmount = 3; // Max step amount

// ZOOM //
const zoomSpeed = 0.01;
const minZoomLevel = 0.0424 / 2;
const maxZoomLevel = 4;
let zoomLevel = 0.0424;

// CENTER MAP (AUTOMATIC) //
let cropx = -(1920 - tileSize * mapSize * zoomLevel) / 2;
let cropy = -(1080 - tileSize * mapSize * zoomLevel) / 2;

// MISC //
const controls = {
    fastForward: "right",
    speedUp: "up",
    stop: "left",
    play: "down",
    debug: "d",
    gif: "g",
    auto: "a"
};

const nnui = { // Neural network UI config
    xoffset: 1920 - 100,
    yoffset: 70,
    xspacing: 10,
    yspacing: 100,
    size: 18,
    stroke: true,
    maxLineSize: 10,
    minLineSize: 5
};<commit_msg>Described more stuff in the config<commit_after>// GLOBAL //
const seed = Math.floor(Math.random() * 999 + 1);
let debugMode = true; // Shows debug info (angle, left and right turn outputs, and tile food)
let gifMode = false; // removes background
let autoMode = false; // automatically calculate timescale

// MAP //
const mapSize = 150; // Size of the map (height and width) in tiles
const tileSize = 250; // Size of the tiles in pixels (at a zoom level of 1)
const selectSizeAddition = 40; // How far around creatures can you click to select them

let maxTileFood = 100; // Maximum food in a tile
const foodRegrowRate = 0.025; // How fast food regrows

const waterBias = 0.4; // Becomes unstable above about 0.75
const distanceSmoothing = 0.5; // less land further away from center
const continentSize = 50; // How large the islands are (maintains water ratio)

const growSeasonLength = 800; // Grow season length
const dieSeasonLength = 1000; // Die season length

const seasonChange = 0.02; // Food grow speed change (added in grow season and subtracted in die season)
const mapUpdateDelay = 100; // How many ticks before the map tiles update

// CREATURES //
const minCreatures = 50; // Minimum number of creatures
const minFirstGen = 10; // Minimum number of first generation creatures

const creatureEnergy = 80; // Max creature energy

const speciesDiversity = 6; // Diversity of each species
const speciesColorChange = 20; // Color change between species

const maxCreatureSize = 100; // Maximum Creature Size
const minCreatureSize = 30; // Minimum Creature Size

const maxCreatureSpeed = 30; // Maximum Creature Speed
const swimmingSpeed = 0.3; // Speed % in water
const agingSpeed = 0.2; // Aging speed percentage %
const eatingSpeed = 0.0; // Speed % while eating

const rotationSpeed = 0.1; // Speed % how fast creatures rotate

let oldest = 0; // oldest creature's age

const maxEyes = 2; // maximum number of "eyes" a creature can have
const maxEyeDistance = 500; // Maximum distance an "eye" can be from a creature

const energy = { // Energy cost per tick
    eat: 0.04, // Energy cost to eat
    metabolism: 0.04, // Energy cost to live
    move: 0.05, // Energy cost to move
    attack: 0.04, // Energy cost to attack
    birth: 1 // Energy cost to birth
};

const eatEffeciency = 0.9; // Eat effeciency %
const birthEffeciency = 0.85; // Birth effeciency %
const attackEffeciency = 2.00; // Attack effeciency %
const attackPower = 3.00; // Attack power %

const minEatPower = 0.0; // Minimum eating strength (anything lower will be 0)
const minReproducePower = 0.0; // Minimum output to reproduce (anything lower will be 0)
const minAttackPower = 0.0; // Minimum attack strength (anything lower will be 0)

const reproduceAge = 1200; // Minimum age when a creature can reproduce
const minReproduceTime = 800; // Minimum time between litters

// Neural Network //
const offset = 0.0; // Amount to offset the value of a neuron
const mutability = 4; // Chance of mutating a single axon

const minStepAmount = Number.EPSILON; // Min step amount (Number.EPSILON is the smallest positive number)
const stepAmount = 3; // Max step amount

// ZOOM //
const zoomSpeed = 0.01; // How fast the zoom happens
const minZoomLevel = 0.0424 / 2; // Furthest zoom
const maxZoomLevel = 4;  // Nearest zoom
let zoomLevel = 0.0424; // Default zoom

// CENTER MAP (AUTOMATIC) //
let cropx = -(1920 - tileSize * mapSize * zoomLevel) / 2;
let cropy = -(1080 - tileSize * mapSize * zoomLevel) / 2;

// MISC //
const controls = {
    fastForward: "right",
    speedUp: "up",
    stop: "left",
    play: "down",
    debug: "d",
    gif: "g",
    auto: "a"
};

const nnui = { // Neural network UI config
    xoffset: 1920 - 100,
    yoffset: 70,
    xspacing: 10,
    yspacing: 100,
    size: 18,
    stroke: true,
    maxLineSize: 10,
    minLineSize: 5
};<|endoftext|>


<commit_before>(function(window, document) {

  "use strict";

  var Escalonador, Estado, Processo, Simulador, btiniciar;

  Estado = {
    NOVO: 0,
    PRONTO: 1,
    EM_ESPERA: 2,
    EM_EXECUCAO: 3,
    ENCERRADO: 4
  };

  Simulador = {

    quantidadeProcessos: 0,

    tabela: document.querySelector("#tabela-processos"),

    debug: false,

    iniciar: function() {
      var quantum = document.querySelector("#quantum").value.trim();
      var quantidadePorMinuto = document.querySelector("#quantidadePorMinuto").value.trim();
      var tempoDeVida = document.querySelector("#tempoDeVida").value.trim();
      var chanceDeEspera = document.querySelector("#chanceDeEspera").value.trim();
      var mostraEncerramento = document.querySelector("#mostraEncerrado").checked;
      var valido = true;

      valido = this.validaInput(1, quantum, quantidadePorMinuto, tempoDeVida) &&
        this.validaInput(0, chanceDeEspera);

      if(valido) {
        this.tabela.innerHTML = "";
        Escalonador.iniciar({
          quantum: quantum,
          quantidadePorMinuto: quantidadePorMinuto,
          chanceDeEspera: chanceDeEspera,
          tempoDeVida: tempoDeVida,
          mostraEncerramento: mostraEncerramento
        });
      }
    },

    validaInput: function() {
      var valorMinimo = arguments[0];

      //Validando somente números
      var regex = /[0-9]*/g;

      for(var i = 1, l = arguments.length; i < l; i++) {
        if(arguments[i] === "" || arguments[i].match(regex)[0] !== arguments[i]) {
          if(valorMinimo && window.parseInt(arguments[i], 10) >= valorMinimo) {
            window.alert("Valor não pode ser zero");
            return false;
          }
          window.alert("Valor dos parâmetros deve ser preenchido e deve ser numérico");
          return false;
        }
      }
      return true;
    },

    adicionaProcesso: function(pid, codEstado) {
      var linha, estado;

      if(this.quantidadeProcessos <= 0) {
        linha = "
PID	ESTADO
";
        this.tabela.innerHTML = linha;
      }

      estado = this.getObjetoEstado(codEstado);
      linha = "
";
      linha += "" + pid + "	";
      linha += "";
      linha += estado.nome +"	";
      linha += "
";
      this.tabela.innerHTML += linha;
      this.quantidadeProcessos++;

    },

    alteraProcesso: function(pid, codEstado) {
      try {
        var processo = document.querySelector("#p" + pid);
        var estado = this.getObjetoEstado(codEstado);
        var elementoTexto = processo.querySelector("td:last-child");
        elementoTexto.className = estado.cor;
        elementoTexto.innerText = estado.nome;
      }
      catch(e) {
        if(this.debug)
          console.error("Processo já removido: " + e.message);
      }
    },

    removeProcesso: function(pid) {
      try {
        var processo = document.querySelector("#p" + pid);
        processo.parentNode.removeChild(processo);
        this.quantidadeProcessos--;
      }
      catch(e) {
        if(this.debug)
          console.error("Processo já removido: " + e.message);
      }
      finally {
        var linha;
        if(this.quantidadeProcessos <= 0) {
          linha = "
Nenhum processo
";
          this.tabela.innerHTML = linha;
        }
      }
    },

    getObjetoEstado: function(estado) {
      switch(estado) {
        case Estado.NOVO:
          return {
            nome: "Novo",
            cor: "preto"
          };
        case Estado.PRONTO:
          return {
            nome: "Pronto",
            cor: "azul"
          };
        case Estado.EM_EXECUCAO:
          return {
            nome: "Executando",
            cor: "verde"
          };
        case Estado.EM_ESPERA:
          return {
            nome: "Esperando",
            cor: "amarelo"
          };
        case Estado.ENCERRADO:
          return {
            nome: "Encerrado",
            cor: "vermelho"
          };
      }
    }
  };

  Processo = (function() {

    Processo.prototype.pid = null;

    Processo.prototype.estado = null;

    Processo.prototype.tempoDeVida = null;

    function Processo(pid, tempoDeVida, mostraEncerramento) {
      this.pid = pid;
      this.estado = Estado.NOVO;
      this.tempoDeVida = tempoDeVida;
      Simulador.adicionaProcesso(pid, this.estado);

      window.setTimeout(this.encerrar.bind(this, mostraEncerramento), this.tempoDeVida);

      //Processo pronto
      this.pronto();
    }

    Processo.prototype.getEstado = function() {
      return this.estado;
    };

    Processo.prototype.pronto = function() {
      if(this.estado !== Estado.ENCERRADO) {
        this.estado = Estado.PRONTO;
        Simulador.alteraProcesso(this.pid, this.estado);
      }
    };

    Processo.prototype.esperar = function() {
      if(this.estado === Estado.EM_EXECUCAO) {
        this.estado = Estado.EM_ESPERA;
        Simulador.alteraProcesso(this.pid, this.estado);
      }
    };

    Processo.prototype.executar = function() {
      if(this.estado === Estado.PRONTO) {
        this.estado = Estado.EM_EXECUCAO;
        Simulador.alteraProcesso(this.pid, this.estado);
      }
    };

    Processo.prototype.encerrar = function(mostraEncerramento) {
      if(this.estado !== Estado.ENCERRADO) {
        this.estado = Estado.ENCERRADO;
        Simulador.alteraProcesso(this.pid, this.estado);
        if(!mostraEncerramento)
          window.setTimeout(this.destruir.bind(this), 3000);
        Escalonador.finalizarProcesso(this.pid);
      }
    };

    Processo.prototype.destruir = function() {
      Simulador.removeProcesso(this.pid);
    };

    return Processo;
  })();

  Escalonador = {

    // Parâmetros do Escalonador.
    // O tempo é expresso em milisegundos

    //Quantidade de tempo que o escalonador leva para trocar o processo
    quantum: null,

    // Tempo para verificar se o quantum foi atingido
    tempoDecorrido: 0,

    //Tempo de vida default do processo: 30 segundos
    tempoDeVida: 30000,

    //Quantidade máxima de processos que são instanciados no minuto
    quantidadePorMinuto: null,

    //Chance do processo entrar em espera
    chanceDeEspera: null,

    //Flag que determina se processos encerrados saem da visualização
    mostraEncerramento: false,

    //Clock do minuto do escalonador
    timerMinuto: null,

    //Clock do segundo do escalonador
    timerSegundo: null,

    //Timer do quantum, troca de processos
    timerExecucao: null,

    proxPid: null,

    processoEmExecucao: null,

    processosNoMinuto: 0,

    processos: {},

    ultimoIndice: 0,

    debug: false,

    verbose: function() {
      this.debug = !this.debug;
      return this.debug;
    },

    //Gera código randômico hexadecimal de 4 dígitos
    R4: function() {
      return ((1 + Math.random())*100000 | 0).toString(16).substring(1);
    },

    //Junta os códigos randômicos para gerar um id único
    geraPID: function() {
      var pid = "" + this.R4() + this.R4();
      pid += "-";
      pid += this.R4() + this.R4();
      pid += "-";
      pid += this.R4();
      return pid;
    },

    iniciar: function(opcoes) {
      this.quantum = opcoes.quantum;
      this.quantidadePorMinuto = opcoes.quantidadePorMinuto;
      this.tempoDeVida = opcoes.tempoDeVida;
      this.chanceDeEspera = opcoes.chanceDeEspera;
      this.mostraEncerramento = opcoes.mostraEncerramento;

      //Zerando escalonador
      this.processos = {};
      this.proxPid = null;
      this.processoEmExecucao = null;
      this.tempoDecorrido = 0;

      if(this.timerMinuto)
        window.clearInterval(this.timerMinuto);

      if(this.timerSegundo)
        window.clearTimeout(this.timerSegundo);

      if(this.timerExecucao)
        window.clearInterval(this.timerExecucao);

      this.processosNoMinuto = 0;
      this.geraLoteDeProcessos();

      //Loop contínuo a cada 60 segundos + 1 que move o Escalonador
      this.timerMinuto = window.setInterval(function(){
        this.processosNoMinuto = 0;
        this.geraLoteDeProcessos();
      }.bind(this), 61000);

      this.timerExecucao = window.setInterval(this.trocaProcesso.bind(this), this.quantum);
    },

    geraLoteDeProcessos: function() {
      var qtde = Math.ceil(this.quantidadePorMinuto/60);
      if(this.processosNoMinuto >= this.quantidadePorMinuto) {
        if(this.debug)
          window.console.log("O lote de processos do minuto foi criado");
      }
      else {
        for(var i = 0; i < qtde; i++) {
          this.criaNovoProcesso();
          this.processosNoMinuto++;
        }
        this.timerSegundo = window.setTimeout(this.geraLoteDeProcessos.bind(this), 1000);
      }
    },

    trocaProcesso: function() {
      var pids, processo, proxPid;

      pids = Object.keys(this.processos);

      if(this.proxPid === null) {
        if(pids[0] !== undefined) {
          this.proxPid = pids[0];
          this.ultimoIndice = 0;
        }
        else {
          return;
        }
      }
      else {
        proxPid = pids[this.ultimoIndice];
        if(proxPid !== undefined) {
          this.proxPid = proxPid;
        }
        else {
          if(pids[0] !== undefined) {
            this.proxPid = pids[0];
            this.ultimoIndice = 0;
          }
          else {
            this.proxPid  = null;
          }
        }
      }

      //Parando execução do processo atual se existente e fora da espera
      if(this.processoEmExecucao !== null) {
        //Pula processos em espera
        if(this.processoEmExecucao.getEstado() === Estado.EM_ESPERA) {
          this.ultimoIndice++;
          return this.trocaProcesso();
        }
        else {
          this.processoEmExecucao.pronto();
        }
      }

      processo = this.getProcesso(this.proxPid);

      //Executa o próximo processo se ele existir
      if (processo) {
        if(processo.getEstado() === Estado.PRONTO) {
          processo.executar();
        }

        this.processoEmExecucao = processo;
        this.ultimoIndice++;
      }
      else {
        this.processoEmExecucao = null;
        this.proxPid = null;
      }

    },

    criaNovoProcesso: function() {
      var pid = this.geraPID();
      var novoProcesso = new Processo(pid, this.tempoDeVida, this.mostraEncerramento);
      this.processos[pid] = novoProcesso;
      if(this.debug) {
        window.console.log("Novo processo adicionado");
        window.console.log(this.processosNoMinuto);
      }
    },

    getProcesso: function(pid) {
      if(this.processos[pid] !== undefined)
        return this.processos[pid];
      else
        return null;
    },

    finalizarProcesso: function(pid) {
      delete this.processos[pid];
      if(this.ultimoIndice > 0) {
        this.ultimoIndice--;
      }
    },
  };

  window.Escalonador = Escalonador;

  //Inicia tudo quando apertado o Iniciar Simulação
  btiniciar = document.querySelector("#btiniciar");
  btiniciar.addEventListener("click", function(e){
    e.preventDefault();
    Simulador.iniciar();
    return false;
  }.bind(this), false);
})(window, document);
<commit_msg>Implementa espera de 1 segundo<commit_after>(function(window, document) {

  "use strict";

  var Escalonador, Estado, Processo, Simulador, btiniciar;

  Estado = {
    NOVO: 0,
    PRONTO: 1,
    EM_ESPERA: 2,
    EM_EXECUCAO: 3,
    ENCERRADO: 4
  };

  Simulador = {

    quantidadeProcessos: 0,

    tabela: document.querySelector("#tabela-processos"),

    debug: false,

    iniciar: function() {
      var quantum = document.querySelector("#quantum").value.trim();
      var quantidadePorMinuto = document.querySelector("#quantidadePorMinuto").value.trim();
      var tempoDeVida = document.querySelector("#tempoDeVida").value.trim();
      var chanceDeEspera = document.querySelector("#chanceDeEspera").value.trim();
      var mostraEncerramento = document.querySelector("#mostraEncerrado").checked;
      var valido = true;

      valido = this.validaInput(1, quantum, quantidadePorMinuto, tempoDeVida) &&
        this.validaInput(0, chanceDeEspera);

      if(valido) {
        this.tabela.innerHTML = "";
        Escalonador.iniciar({
          quantum: quantum,
          quantidadePorMinuto: quantidadePorMinuto,
          chanceDeEspera: chanceDeEspera,
          tempoDeVida: tempoDeVida,
          mostraEncerramento: mostraEncerramento
        });
      }
    },

    validaInput: function() {
      var valorMinimo = arguments[0];

      //Validando somente números
      var regex = /[0-9]*/g;

      for(var i = 1, l = arguments.length; i < l; i++) {
        if(arguments[i] === "" || arguments[i].match(regex)[0] !== arguments[i]) {
          if(valorMinimo && window.parseInt(arguments[i], 10) >= valorMinimo) {
            window.alert("Valor não pode ser zero");
            return false;
          }
          window.alert("Valor dos parâmetros deve ser preenchido e deve ser numérico");
          return false;
        }
      }
      return true;
    },

    adicionaProcesso: function(pid, codEstado) {
      var linha, estado;

      if(this.quantidadeProcessos <= 0) {
        linha = "
PID	ESTADO
";
        this.tabela.innerHTML = linha;
      }

      estado = this.getObjetoEstado(codEstado);
      linha = "
";
      linha += "" + pid + "	";
      linha += "";
      linha += estado.nome +"	";
      linha += "
";
      this.tabela.innerHTML += linha;
      this.quantidadeProcessos++;

    },

    alteraProcesso: function(pid, codEstado) {
      try {
        var processo = document.querySelector("#p" + pid);
        var estado = this.getObjetoEstado(codEstado);
        var elementoTexto = processo.querySelector("td:last-child");
        elementoTexto.className = estado.cor;
        elementoTexto.innerText = estado.nome;
      }
      catch(e) {
        if(this.debug)
          window.console.error("Processo já removido: " + e.message);
      }
    },

    removeProcesso: function(pid) {
      try {
        var processo = document.querySelector("#p" + pid);
        processo.parentNode.removeChild(processo);
        this.quantidadeProcessos--;
      }
      catch(e) {
        this.quantidadeProcessos--;
        if(this.debug)
          window.console.error("Processo já removido: " + e.message);
      }
      finally {
        var linha;
        if(this.quantidadeProcessos <= 0) {
          this.quantidadeProcessos = 0;
          linha = "
Nenhum processo
";
          this.tabela.innerHTML = linha;
        }
      }
    },

    getObjetoEstado: function(estado) {
      switch(estado) {
        case Estado.NOVO:
          return {
            nome: "Novo",
            cor: "preto"
          };
        case Estado.PRONTO:
          return {
            nome: "Pronto",
            cor: "azul"
          };
        case Estado.EM_EXECUCAO:
          return {
            nome: "Executando",
            cor: "verde"
          };
        case Estado.EM_ESPERA:
          return {
            nome: "Esperando",
            cor: "amarelo"
          };
        case Estado.ENCERRADO:
          return {
            nome: "Encerrado",
            cor: "vermelho"
          };
      }
    }
  };

  Processo = (function() {

    Processo.prototype.pid = null;

    Processo.prototype.estado = null;

    Processo.prototype.tempoDeVida = null;

    Processo.prototype.chanceDeEspera = null;

    function Processo(pid, tempoDeVida, mostraEncerramento, chanceDeEspera) {
      this.pid = pid;
      this.estado = Estado.NOVO;
      this.tempoDeVida = tempoDeVida;
      this.chanceDeEspera = chanceDeEspera;
      Simulador.adicionaProcesso(pid, this.estado);

      window.setTimeout(this.encerrar.bind(this, mostraEncerramento), this.tempoDeVida);

      //Processo pronto
      this.pronto();
    }

    Processo.prototype.getEstado = function() {
      return this.estado;
    };

    Processo.prototype.pronto = function() {
      if(this.estado !== Estado.ENCERRADO) {
        this.estado = Estado.PRONTO;
        Simulador.alteraProcesso(this.pid, this.estado);
      }
    };

    Processo.prototype.entraEmEspera = function() {
      var porcentagemDeChance = this.chanceDeEspera;
      var random = ((Math.random()*100)+1);
      if(random <= porcentagemDeChance) {
        window.setTimeout(this.pronto.bind(this), 1000);
        Escalonador.contadorEspera++;
        return true;
      }
      Escalonador.contadorExecutou++;
      return false;
    };

    Processo.prototype.esperar = function() {
      if(this.estado === Estado.EM_EXECUCAO) {
        this.estado = Estado.EM_ESPERA;
        Simulador.alteraProcesso(this.pid, this.estado);
      }
    };

    Processo.prototype.executar = function() {
      if(this.estado === Estado.PRONTO && !this.entraEmEspera()) {
        this.estado = Estado.EM_EXECUCAO;
        Simulador.alteraProcesso(this.pid, this.estado);
      }
      else {
        this.estado = Estado.EM_ESPERA;
        Simulador.alteraProcesso(this.pid, this.estado);
      }
    };

    Processo.prototype.encerrar = function(mostraEncerramento) {
      if(this.estado !== Estado.ENCERRADO) {
        this.estado = Estado.ENCERRADO;
        Simulador.alteraProcesso(this.pid, this.estado);
        if(!mostraEncerramento)
          window.setTimeout(this.destruir.bind(this), 3000);
        Escalonador.finalizarProcesso(this.pid);
      }
    };

    Processo.prototype.destruir = function() {
      Simulador.removeProcesso(this.pid);
    };

    return Processo;
  })();

  Escalonador = {

    // Parâmetros do Escalonador.
    // O tempo é expresso em milisegundos

    //Quantidade de tempo que o escalonador leva para trocar o processo
    quantum: null,

    // Tempo para verificar se o quantum foi atingido
    tempoDecorrido: 0,

    //Tempo de vida default do processo: 30 segundos
    tempoDeVida: 30000,

    //Quantidade máxima de processos que são instanciados no minuto
    quantidadePorMinuto: null,

    //Chance do processo entrar em espera
    chanceDeEspera: null,

    //Flag que determina se processos encerrados saem da visualização
    mostraEncerramento: false,

    //Clock do minuto do escalonador
    timerMinuto: null,

    //Clock do segundo do escalonador
    timerSegundo: null,

    //Timer do quantum, troca de processos
    timerExecucao: null,

    proxPid: null,

    processoEmExecucao: null,

    processosNoMinuto: 0,

    processos: {},

    ultimoIndice: 0,

    //Debug espera
    contadorEspera: 0,

    contadorExecutou: 0,

    debug: false,

    verbose: function() {
      this.debug = !this.debug;
      return this.debug;
    },

    //Gera código randômico hexadecimal de 4 dígitos
    R4: function() {
      return ((1 + Math.random())*100000 | 0).toString(16).substring(1);
    },

    //Junta os códigos randômicos para gerar um id único
    geraPID: function() {
      var pid = "" + this.R4() + this.R4();
      pid += "-";
      pid += this.R4() + this.R4();
      pid += "-";
      pid += this.R4();
      return pid;
    },

    iniciar: function(opcoes) {
      this.quantum = opcoes.quantum;
      this.quantidadePorMinuto = opcoes.quantidadePorMinuto;
      this.tempoDeVida = opcoes.tempoDeVida;
      this.chanceDeEspera = opcoes.chanceDeEspera;
      this.mostraEncerramento = opcoes.mostraEncerramento;

      //Zerando escalonador
      this.processos = {};
      this.proxPid = null;
      this.processoEmExecucao = null;
      this.tempoDecorrido = 0;
      this.contadorExecutou = 0;
      this.contadorEspera = 0;

      if(this.timerMinuto)
        window.clearInterval(this.timerMinuto);

      if(this.timerSegundo)
        window.clearTimeout(this.timerSegundo);

      if(this.timerExecucao)
        window.clearInterval(this.timerExecucao);

      this.processosNoMinuto = 0;
      this.geraLoteDeProcessos();

      //Loop contínuo a cada 60 segundos + 1 que move o Escalonador
      this.timerMinuto = window.setInterval(function(){
        this.processosNoMinuto = 0;
        this.geraLoteDeProcessos();
      }.bind(this), 61000);

      this.timerExecucao = window.setInterval(this.trocaProcesso.bind(this), this.quantum);
    },

    geraLoteDeProcessos: function() {
      var qtde = Math.ceil(this.quantidadePorMinuto/60);
      if(this.processosNoMinuto >= this.quantidadePorMinuto) {
        if(this.debug) {
          window.console.log("O lote de processos do minuto foi criado");
          window.console.log("NUMERO DE ESPERA: " + this.contadorEspera);
          window.console.log("NUMERO EXECUTADO: " + this.contadorExecutou);
          this.contadorEspera = 0;
          this.contadorExecutou = 0;
        }
      }
      else {
        for(var i = 0; i < qtde; i++) {
          this.criaNovoProcesso();
          this.processosNoMinuto++;
        }
        this.timerSegundo = window.setTimeout(this.geraLoteDeProcessos.bind(this), 1000);
      }
    },

    trocaProcesso: function() {
      var pids, processo, proxPid;

      pids = Object.keys(this.processos);

      if(this.proxPid === null) {
        if(pids[0] !== undefined) {
          this.proxPid = pids[0];
          this.ultimoIndice = 0;
        }
        else {
          return;
        }
      }
      else {
        proxPid = pids[this.ultimoIndice];
        if(proxPid !== undefined) {
          this.proxPid = proxPid;
        }
        else {
          if(pids[0] !== undefined) {
            this.proxPid = pids[0];
            this.ultimoIndice = 0;
          }
          else {
            this.proxPid  = null;
          }
        }
      }

      //Parando execução do processo atual se existente e fora da espera
      if(this.processoEmExecucao !== null) {
        //Pula processos em espera
        if(this.processoEmExecucao.getEstado() !== Estado.EM_ESPERA)
          this.processoEmExecucao.pronto();
      }

      processo = this.getProcesso(this.proxPid);

      //Executa o próximo processo se ele existir
      if (processo) {
        //Pula processos em espera
        if(processo.getEstado() === Estado.EM_ESPERA) {
          this.ultimoIndice++;
          return;
        }

        if(processo.getEstado() === Estado.PRONTO) {
          processo.executar();
        }

        this.processoEmExecucao = processo;

        this.ultimoIndice++;
      }
      else {
        this.processoEmExecucao = null;
        this.proxPid = null;
      }

    },

    criaNovoProcesso: function() {
      var pid = this.geraPID();
      var novoProcesso = new Processo(pid, this.tempoDeVida, this.mostraEncerramento, this.chanceDeEspera);
      this.processos[pid] = novoProcesso;
      if(this.debug) {
        window.console.log("Novo processo adicionado");
        window.console.log(this.processosNoMinuto);
      }
    },

    getProcesso: function(pid) {
      if(this.processos[pid] !== undefined)
        return this.processos[pid];
      else
        return null;
    },

    finalizarProcesso: function(pid) {
      delete this.processos[pid];
      if(this.ultimoIndice > 0) {
        this.ultimoIndice--;
      }
    },
  };

  window.Escalonador = Escalonador;

  //Inicia tudo quando apertado o Iniciar Simulação
  btiniciar = document.querySelector("#btiniciar");
  btiniciar.addEventListener("click", function(e){
    e.preventDefault();
    Simulador.iniciar();
    return false;
  }.bind(this), false);
})(window, document);
<|endoftext|>


<commit_before>#!/usr/bin/env node
const isProdRelease = process.env.BRANCH && process.env.BRANCH === "master"
const isPublishCommit = process.env.PUBLISH_COMMIT && process.env.PUBLISH_COMMIT === "Publish"
const spawn = require('cross-spawn');
const exec = require('child_process').execSync;

const spawnWithErrorHandling = (...args) => {
  const results = spawn.sync(...args);
  if (results.error) {
    throw results.error;
  }
};

// Set dist-tag
const tasks = [
  'run',
  'lerna',
  'publish',
  '--',
  '--yes'
]

if (!isProdRelease) { // pre-release
  tasks.push('--cd-version=prerelease')
} else {
  tasks.push('--conventional-commits')
}

if (isPublishCommit) {

  // Publish packages to npm registry
  spawnWithErrorHandling('npm', tasks, { stdio: 'inherit' });

  console.log('Pushing commit...');
  exec('git checkout staging');
  exec('git add .');
  exec(`git commit -m 'Publish'`);
  exec(`git push origin ${process.env.BRANCH}`);

  console.log('Done!');

}
<commit_msg>fix publish<commit_after>#!/usr/bin/env node
const isProdRelease = process.env.BRANCH && process.env.BRANCH === "master"
const isPublishCommit = process.env.PUBLISH_COMMIT && process.env.PUBLISH_COMMIT === "Publish"
const spawn = require('cross-spawn');
const exec = require('child_process').execSync;

const spawnWithErrorHandling = (...args) => {
  const results = spawn.sync(...args);
  if (results.error) {
    throw results.error;
  }
};

// Set dist-tag
const tasks = [
  'run',
  'lerna',
  'publish',
  '--',
  '--yes'
]

if (!isProdRelease) { // pre-release
  tasks.push('--cd-version=prerelease')
} else {
  tasks.push('--conventional-commits')
}

if (!isPublishCommit) {

  // Publish packages to npm registry
  spawnWithErrorHandling('npm', tasks, { stdio: 'inherit' });

  console.log('Pushing commit...');
  exec('git add .');
  exec(`git commit -m 'Publish'`);
  exec(`git push origin ${process.env.BRANCH}`);

  console.log('Done!');

}
<|endoftext|>


<commit_before>var async = require('async');
var AWS = require('aws-sdk');
var env = require('../lib/environment');

var Mongoose = require('mongoose');
Mongoose.connect(env.get('MONGO_URL'));
var Make = require('../lib/models/make')(Mongoose);
var S3 = new AWS.S3({
  region: 'us-east-1',
  params: {
    Bucket: env.get('S3_EXPORT_BUCKET'),
    ContentType: 'application/json; charset=utf-8',
    CacheControl: 'public, max-age=86400'
  }
});

var countDocuments = function(callback) {
  Make.count({
    deletedAt: null
  }, callback);
};

var fetchDocuments = function(totalDocuments, callback) {
  var documentsFetched = 0;
  var increment = 2500;
  var aggregatedMakes = {};

  async.whilst(
    function test() {
      return documentsFetched < totalDocuments;
    },
    function work(callback) {
      process.stdout.clearLine();
      process.stdout.cursorTo(0);
      process.stdout.write(documentsFetched + "/" + totalDocuments + " fetched");

      Make.aggregate([
        {
          $match: {
            deletedAt: null
          }
        },
        { $skip: documentsFetched },
        { $limit: increment },
        {
          $group: {
            _id: {
              email: '$email'
            },
            makes: {
              $push: {
                id: '$_id.oid',
                contentType: '$contentType',
                createdAt: '$createdAt',
                description: '$description',
                editurl: '$editurl',
                locale: '$locale',
                remixedFrom: '$remixedFrom',
                remixurl: '$remixurl',
                thumbnail: '$thumbnail',
                title: '$title',
                updatedAt: '$updatedAt',
                url: '$url'
              }
            }
          }
        },
        {
          $project: {
            _id: 0,
            email: '$_id.email',
            makes: '$makes'
          }
        }
      ], function(error, results) {
        if (error) {
          return callback(error);
        }

        results.forEach(function(result) {
          if (!aggregatedMakes[result.email]) {
            aggregatedMakes[result.email] = [];
          }

          aggregatedMakes[result.email] = aggregatedMakes[result.email].concat(result.makes);
        });

        documentsFetched += increment;

        callback();
      });
    },
    function done(error) {
      Mongoose.disconnect();

      process.stdout.clearLine();
      process.stdout.cursorTo(0);
      process.stdout.write(totalDocuments + "/" + totalDocuments + " fetched\n");

      callback(error, aggregatedMakes);
    }
  );
};

var loginURL = require("url").parse(env.get('LOGIN_SERVER_URL_WITH_AUTH'));
var fetchUser = require("request").defaults({
  method: 'GET',
  baseUrl: loginURL.protocol + '//' + loginURL.host,
  auth: {
    user: loginURL.auth.split(':')[0],
    pass: loginURL.auth.split(':')[1]
  },
  json: true
});

var processDocuments = function(aggregatedMakes, callback) {
  var emails = Object.keys(aggregatedMakes);
  var exported = 0;
  var totalExports = emails.length;

  var q = async.queue(function(email, callback) {
    async.waterfall([
      async.retry(async.apply(fetchUser, { url: '/user/email/' + email })),
      function(response, callback) {
        if (response.statusCode === 404) {
          return callback();
        }

        var obj = {
          username: response.body.user.username,
          makes: aggregatedMakes[email]
        };

        callback(null, obj);
      },
      function(usersMakes, callback) {
        process.stdout.clearLine();
        process.stdout.cursorTo(0);
        process.stdout.write(exported++ + "/" + totalExports + " exported");

        if (!callback) {
          return usersMakes();
        }

        S3.putObject({
          Key: usersMakes.username + '/makes.json',
          Body: new Buffer(JSON.stringify(usersMakes.makes), 'utf8')
        }, callback);
      }
    ], callback);
  }, 20);

  q.drain = callback;
  q.push(emails);
};

async.waterfall([
  countDocuments,
  fetchDocuments,
  processDocuments
], function(error, result) {
  if (error) {
    throw error;
  }
});
<commit_msg>Oh well<commit_after><|endoftext|>