<commit_before>osg.StateGraph = function () {
    this.depth = 0;
    this.children = {};
    this.children.keys = [];
    this.leafs = [];
    this.stateset = undefined;
    this.parent = undefined;
};

osg.StateGraph.prototype = {
    clean: function() {
        this.leafs = undefined;
        this.stateset = undefined;
        this.parent = undefined;
        //this.depth = 0;
        for (var i = 0, l = this.children.keys.length; i < l; i++) {
            var key = this.children.keys[i];
            this.children[key].clean();
        }
        this.children = {};
        this.children.keys = [];
    },
    getStateSet: function() { return this.stateset; },
    findOrInsert: function (stateset)
    {
        var sg;
        if (!this.children[stateset.id]) {
            sg = new osg.StateGraph();
            sg.parent = this;
            sg.depth = this.depth + 1;
            sg.stateset = stateset;
            this.children[stateset.id] = sg;
            this.children.keys.push(stateset.id);
        } else {
            sg = this.children[stateset.id];
        }
        return sg;
    },
    moveToRootStateGraph: function(state, sg_current)
    {
        // need to pop back all statesets and matrices.
        while (sg_current)
        {
            if (sg_current.stateSet) {
                state.popStateSet();
            }
            sg_current = sg_current._parent;
        }
    },
    moveStateGraph: function(state, sg_current, sg_new)
    {
        var stack;
        var i;
        if (sg_new === sg_current || sg_new === undefined) {
            return;
        }

        if (sg_current === undefined) {
            stack = [];
            // push stateset from sg_new to root, and apply
            // stateset from root to sg_new
            do {
                if (sg_new.stateset !== undefined) {
                    stack.push(sg_new.stateset);
                }
                sg_new = sg_new.parent;
            } while (sg_new);

            stack.reverse();
            for (i = 0, l = stack.length; i < l; ++i) {
                state.pushStateSet(stack[i]);
            }
            return;
        } else if (sg_current.parent === sg_new.parent) {
            // first handle the typical case which is two state groups
            // are neighbours.

            // state has changed so need to pop old state.
            if (sg_current.stateset !== undefined) {
                state.popStateSet();
            }
            // and push new state.
            if (sg_new.stateset !== undefined) {
                state.pushStateSet(sg_new.stateset);
            }
            return;
        }

        // need to pop back up to the same depth as the new state group.
        while (sg_current.depth > sg_new.depth)
        {
            if (sg_current.stateset !== undefined) {
                state.popStateSet();
            }
            sg_current = sg_current.parent;
        }

        // use return path to trace back steps to sg_new.
        stack = [];

        // need to pop back up to the same depth as the curr state group.
        while (sg_new.depth > sg_current.depth)
        {
            if (sg_new.stateset !== undefined) {
                stack.push(sg_new.stateset);
            }
            sg_new = sg_new.parent;
        }

        // now pop back up both parent paths until they agree.

        // DRT - 10/22/02
        // should be this to conform with above case where two StateGraph
        // nodes have the same parent
        while (sg_current !== sg_new)
        {
            if (sg_current.stateset !== undefined) {
                state.popStateSet();
            }
            sg_current = sg_current.parent;

            if (sg_new.stateset !== undefined) {
                stack.push(sg_new.stateset);
            }
            sg_new = sg_new.parent;
        }

        stack.reverse();
        stackLength = stack.length;
        for( i = 0; i < stackLength; ++i) {
            state.pushStateSet(stack[i]);
        }
    }
};
<commit_msg>splice to clean array<commit_after>osg.StateGraph = function () {
    this.depth = 0;
    this.children = {};
    this.children.keys = [];
    this.leafs = [];
    this.stateset = undefined;
    this.parent = undefined;
};

osg.StateGraph.prototype = {
    clean: function() {
        this.leafs.splice(0, this.leafs.length);
        this.stateset = undefined;
        this.parent = undefined;
        //this.depth = 0;
        var keys = this.children.keys;
        for (var i = 0, l = keys.length; i < l; i++) {
            var key = keys[i];
            this.children[key].clean();
        }
        this.children = {};
        keys.splice(0, keys.length);
        this.children.keys = keys;
    },
    getStateSet: function() { return this.stateset; },
    findOrInsert: function (stateset)
    {
        var sg;
        if (!this.children[stateset.id]) {
            sg = new osg.StateGraph();
            sg.parent = this;
            sg.depth = this.depth + 1;
            sg.stateset = stateset;
            this.children[stateset.id] = sg;
            this.children.keys.push(stateset.id);
        } else {
            sg = this.children[stateset.id];
        }
        return sg;
    },
    moveToRootStateGraph: function(state, sg_current)
    {
        // need to pop back all statesets and matrices.
        while (sg_current)
        {
            if (sg_current.stateSet) {
                state.popStateSet();
            }
            sg_current = sg_current._parent;
        }
    },
    moveStateGraph: function(state, sg_current, sg_new)
    {
        var stack;
        var i;
        if (sg_new === sg_current || sg_new === undefined) {
            return;
        }

        if (sg_current === undefined) {
            stack = [];
            // push stateset from sg_new to root, and apply
            // stateset from root to sg_new
            do {
                if (sg_new.stateset !== undefined) {
                    stack.push(sg_new.stateset);
                }
                sg_new = sg_new.parent;
            } while (sg_new);

            stack.reverse();
            for (i = 0, l = stack.length; i < l; ++i) {
                state.pushStateSet(stack[i]);
            }
            return;
        } else if (sg_current.parent === sg_new.parent) {
            // first handle the typical case which is two state groups
            // are neighbours.

            // state has changed so need to pop old state.
            if (sg_current.stateset !== undefined) {
                state.popStateSet();
            }
            // and push new state.
            if (sg_new.stateset !== undefined) {
                state.pushStateSet(sg_new.stateset);
            }
            return;
        }

        // need to pop back up to the same depth as the new state group.
        while (sg_current.depth > sg_new.depth)
        {
            if (sg_current.stateset !== undefined) {
                state.popStateSet();
            }
            sg_current = sg_current.parent;
        }

        // use return path to trace back steps to sg_new.
        stack = [];

        // need to pop back up to the same depth as the curr state group.
        while (sg_new.depth > sg_current.depth)
        {
            if (sg_new.stateset !== undefined) {
                stack.push(sg_new.stateset);
            }
            sg_new = sg_new.parent;
        }

        // now pop back up both parent paths until they agree.

        // DRT - 10/22/02
        // should be this to conform with above case where two StateGraph
        // nodes have the same parent
        while (sg_current !== sg_new)
        {
            if (sg_current.stateset !== undefined) {
                state.popStateSet();
            }
            sg_current = sg_current.parent;

            if (sg_new.stateset !== undefined) {
                stack.push(sg_new.stateset);
            }
            sg_new = sg_new.parent;
        }

        stack.reverse();
        stackLength = stack.length;
        for( i = 0; i < stackLength; ++i) {
            state.pushStateSet(stack[i]);
        }
    }
};
<|endoftext|>


<commit_before>// PLUGIN: Twitter

(function ( Popcorn, global ) {

  Popcorn.plugin( "twitter", {
    manifest: {
      about: {
        name: "Popcorn Maker Twitter Plugin",
        version: "0.1",
        author: "Matthew Schranz, @mjschranz",
        website: "mschranz.wordpress.com, http://github.com/mjschranz"
      },
      options: {
        start: {
          elem: "input",
          type: "number",
          label: "Start",
          units: "seconds"
        },
        end: {
          elem: "input",
          type: "number",
          label: "End",
          units: "seconds"
        },
        search: {
          elem: "input",
          type: "text",
          label: "Search",
          "default": "Kittens",
          optional: true
        },
        username: {
          elem: "input",
          type: "text",
          label: "Tweets from User",
          optional: true
        },
        searchType: {
          elem: "select",
          options: [ "Mixed", "Recent", "Popular" ],
          values: [ "mixed", "recent", "popular" ],
          label: "Search Results",
          "default": "mixed",
          "hidden": true
        },
        numberOfTweets: {
          elem: "input",
          type: "number",
          label: "Number of Tweets",
          "default": 10,
          optional: true
        },
        transition: {
          elem: "select",
          options: [ "None", "Pop", "Fade", "Slide Up", "Slide Down" ],
          values: [ "popcorn-none", "popcorn-pop", "popcorn-fade", "popcorn-slide-up", "popcorn-slide-down" ],
          label: "Transition",
          "default": "popcorn-fade"
        },
        layout: {
          elem: "select",
          options: [ "Ticker", "Feed" ],
          values: [ "ticker", "feed" ],
          label: "Tweet Layout",
          "default": "feed",
          optional: true
        },
        top: {
          hidden: true,
          elem: "input",
          type: "number",
          units: "%",
          "default": 10
        },
        left: {
          hidden: true,
          elem: "input",
          type: "number",
          units: "%",
          "default": 10
        },
        zindex: {
          hidden: true
        }
      }
    },
    _setup: function( options ) {
      var target = Popcorn.dom.find( options.target ),
          requestString = "http://api.twitter.com/1/statuses/user_timeline.json?screen_name=",
          titleText = document.createElement( "span" ),
          outerTweetsContainer = document.createElement( "div" ),
          tweetsContainer = document.createElement( "ul" ),
          img,
          tweetContainer,
          imgLink,
          tweetTextCont,
          tweetUser,
          tweetText,
          allTweets = [],
          numberOfTweets = options.numberOfTweets;

      if ( !target ) {
        target = this.media.parentNode;
      }

      options._target = target;

      if ( !numberOfTweets ) {
        numberOfTweets = options._natives.manifest.options.numberOfTweets[ "default" ];
      } else if ( numberOfTweets === 0 ) {
        numberOfTweets = 1;
      } else if ( options.username && numberOfTweets > 20 ) {
        // Requests for a specific user will only return a max of 20
        numberOfTweets = 20;
      }

      // safeguard against no search/username being provided
      if ( !options.search && !options.username ) {
        options.search = options._natives.manifest.options.search[ "default" ];
      }

      options._container = document.createElement( "div" );
      options._container.classList.add( "popcorn-twitter" );
      options._container.id = Popcorn.guid( "twitter" );
      options._container.style.top = options.top + "%";
      options._container.style.left = options.left + "%";
      options._container.style.zIndex = +options.zindex;
      titleText.classList.add( "popcorn-twitter-title" );
      titleText.appendChild( document.createTextNode( options.search || options.username || "Twitter" ) );

      // Set layout class for container
      if ( options.layout ) {
        options._container.classList.add( options.layout );
      }

      // Set transitions for container
      if ( options.layout !== "ticker" ) {
        options._container.classList.add( options.transition );
        options._container.classList.add( "off" );
      }
      options._container.appendChild( titleText );

      function twitterCallback( e ) {
        var results = e.results || e,
            currTweet,
            twitterHandle,
            twitterName,
            imageLinkSource,
            i,
            k,
            rLen;

        function buildTheTweets() {

          rLen = allTweets.length;

          for ( i = 0; i < rLen; i++ ) {
            currTweet = allTweets[ i ];
            tweetContainer = document.createElement( "li" );
            img = document.createElement( "img" );
            imgLink = document.createElement( "a" );
            tweetTextCont = document.createElement( "div" );
            tweetUser = document.createElement( "div" );
            tweetUser.classList.add( "popcorn-twitter-tweet-user" );
            tweetText = document.createElement( "div" );
            tweetText.classList.add( "popcorn-twitter-tweet-text" );
            imageLinkSource = currTweet.profile_image_url || currTweet.user.profile_image_url;
            twitterHandle = currTweet.from_user || currTweet.user.screen_name,
            twitterName = currTweet.from_user_name || currTweet.user.name;

            imgLink.classList.add( "popcorn-twitter-tweet-image" );
            imgLink.href = img.src = imageLinkSource;
            imgLink.target = "_blank"; // Ensure it opens in new tab/window
            imgLink.appendChild( img );
            tweetContainer.appendChild( imgLink );

            // Text Setup
            tweetText.innerHTML = currTweet.text;
            tweetUser.innerHTML = "" +
                                  twitterName + " @" + twitterHandle;
            tweetTextCont.appendChild( tweetUser );
            tweetTextCont.appendChild( tweetText );
            tweetContainer.appendChild( tweetTextCont );
            tweetsContainer.appendChild( tweetContainer );
          }

          outerTweetsContainer.classList.add( "popcorn-twitter-tweets" );
          outerTweetsContainer.appendChild( tweetsContainer );
          options._container.appendChild( outerTweetsContainer );
        }

        for ( k = 0, rLen = results.length; k < rLen && allTweets.length < options.numberOfTweets; k++ ) {
          allTweets.push( results[ k ] );
        }

        // Search API doesn't simply return count of tweets. It returns up to 100
        // and then provides a link to query the next "Page" of the same results
        if ( allTweets.length < options.numberOfTweets && options.search ) {
          Popcorn.xhr({
            url: requestString.substring( 0, requestString.indexOf( "?" ) ) + e.next_page,
            dataType: "jsonp",
            success: twitterCallback
          });
        } else {
          buildTheTweets();
        }

      }

      target.appendChild( options._container );

      // Append various query options here
      requestString += options.username +
                       "&count=" + options.numberOfTweets + "&include_rts=true";

      if ( options.search ) {
        requestString = "http://search.twitter.com/search.json?q=";

        requestString += options.search +
                       "&result_type=" + options.searchType;
      }

      Popcorn.xhr( { url: requestString, dataType: "jsonp", success: twitterCallback } );

      options.toString = function() {
        return options.username || options.search || options._natives.manifest.options.search[ "default" ];
      };
    },
    start: function( event, options ) {
      if ( options._container ) {
        options._container.classList.add( "on" );
        options._container.classList.remove( "off" );
      }
    },
    end: function( event, options ) {
      if ( options._container ) {
        options._container.classList.add( "off" );
        options._container.classList.remove( "on" );
      }
    },
    _teardown: function( options ) {
      // Remove the plugins container when being destroyed
      if ( options._container && options._target ) {
        options._target.removeChild( options._container );
      }
    }
  });
}( Popcorn, this ));
<commit_msg>[#1959] Preventative measures against hitting the rate limiting of Twitter API<commit_after>// PLUGIN: Twitter

(function ( Popcorn, global ) {

  var CACHED_RESULTS = {};

  Popcorn.plugin( "twitter", {
    manifest: {
      about: {
        name: "Popcorn Maker Twitter Plugin",
        version: "0.1",
        author: "Matthew Schranz, @mjschranz",
        website: "mschranz.wordpress.com, http://github.com/mjschranz"
      },
      options: {
        start: {
          elem: "input",
          type: "number",
          label: "Start",
          units: "seconds"
        },
        end: {
          elem: "input",
          type: "number",
          label: "End",
          units: "seconds"
        },
        search: {
          elem: "input",
          type: "text",
          label: "Search",
          "default": "Kittens",
          optional: true
        },
        username: {
          elem: "input",
          type: "text",
          label: "Tweets from User",
          optional: true
        },
        searchType: {
          elem: "select",
          options: [ "Mixed", "Recent", "Popular" ],
          values: [ "mixed", "recent", "popular" ],
          label: "Search Results",
          "default": "mixed",
          "hidden": true
        },
        numberOfTweets: {
          elem: "input",
          type: "number",
          label: "Number of Tweets",
          "default": 10,
          optional: true
        },
        transition: {
          elem: "select",
          options: [ "None", "Pop", "Fade", "Slide Up", "Slide Down" ],
          values: [ "popcorn-none", "popcorn-pop", "popcorn-fade", "popcorn-slide-up", "popcorn-slide-down" ],
          label: "Transition",
          "default": "popcorn-fade"
        },
        layout: {
          elem: "select",
          options: [ "Ticker", "Feed" ],
          values: [ "ticker", "feed" ],
          label: "Tweet Layout",
          "default": "feed",
          optional: true
        },
        top: {
          hidden: true,
          elem: "input",
          type: "number",
          units: "%",
          "default": 10
        },
        left: {
          hidden: true,
          elem: "input",
          type: "number",
          units: "%",
          "default": 10
        },
        zindex: {
          hidden: true
        }
      }
    },
    _setup: function( options ) {
      var target = Popcorn.dom.find( options.target ),
          requestString = "http://api.twitter.com/1/statuses/user_timeline.json?screen_name=",
          titleText = document.createElement( "span" ),
          outerTweetsContainer = document.createElement( "div" ),
          tweetsContainer = document.createElement( "ul" ),
          img,
          tweetContainer,
          imgLink,
          tweetTextCont,
          tweetUser,
          tweetText,
          allTweets = [],
          query,
          numberOfTweets = options.numberOfTweets;

      if ( !target ) {
        target = this.media.parentNode;
      }

      options._target = target;

      if ( !numberOfTweets ) {
        numberOfTweets = options._natives.manifest.options.numberOfTweets[ "default" ];
      } else if ( numberOfTweets === 0 ) {
        numberOfTweets = 1;
      } else if ( options.username && numberOfTweets > 20 ) {
        // Requests for a specific user will only return a max of 20
        numberOfTweets = 20;
      }

      // safeguard against no search/username being provided
      if ( !options.search && !options.username ) {
        options.search = options._natives.manifest.options.search[ "default" ];
      }

      options._container = document.createElement( "div" );
      options._container.classList.add( "popcorn-twitter" );
      options._container.id = Popcorn.guid( "twitter" );
      options._container.style.top = options.top + "%";
      options._container.style.left = options.left + "%";
      options._container.style.zIndex = +options.zindex;
      titleText.classList.add( "popcorn-twitter-title" );
      titleText.appendChild( document.createTextNode( options.search || options.username || "Twitter" ) );

      // Set layout class for container
      if ( options.layout ) {
        options._container.classList.add( options.layout );
      }

      // Set transitions for container
      if ( options.layout !== "ticker" ) {
        options._container.classList.add( options.transition );
        options._container.classList.add( "off" );
      }
      options._container.appendChild( titleText );

      query = options.search || options.username;

      function buildTheTweets( tweets ) {
        var currTweet,
            twitterHandle,
            twitterName,
            imageLinkSource,
            i,
            len;

        // If we made it here, the query was a new one so store it in our cache
        CACHED_RESULTS[ query ] = tweets;

        len = tweets.length;

        for ( i = 0; i < len; i++ ) {
          currTweet = tweets[ i ];
          tweetContainer = document.createElement( "li" );
          img = document.createElement( "img" );
          imgLink = document.createElement( "a" );
          tweetTextCont = document.createElement( "div" );
          tweetUser = document.createElement( "div" );
          tweetUser.classList.add( "popcorn-twitter-tweet-user" );
          tweetText = document.createElement( "div" );
          tweetText.classList.add( "popcorn-twitter-tweet-text" );
          imageLinkSource = currTweet.profile_image_url || currTweet.user.profile_image_url;
          twitterHandle = currTweet.from_user || currTweet.user.screen_name;
          twitterName = currTweet.from_user_name || currTweet.user.name;

          imgLink.classList.add( "popcorn-twitter-tweet-image" );
          imgLink.href = img.src = imageLinkSource;
          imgLink.target = "_blank"; // Ensure it opens in new tab/window
          imgLink.appendChild( img );
          tweetContainer.appendChild( imgLink );

          // Text Setup
          tweetText.innerHTML = currTweet.text;
          tweetUser.innerHTML = "" +
                                twitterName + " @" + twitterHandle;
          tweetTextCont.appendChild( tweetUser );
          tweetTextCont.appendChild( tweetText );
          tweetContainer.appendChild( tweetTextCont );
          tweetsContainer.appendChild( tweetContainer );
        }

        // Set layout class for container
        if ( options.layout ) {
          options._container.classList.add( options.layout );
        }

        outerTweetsContainer.classList.add( "popcorn-twitter-tweets" );
        outerTweetsContainer.appendChild( tweetsContainer );
        options._container.appendChild( outerTweetsContainer );
      }

      function twitterCallback( e ) {
        var results = e.results || e,
            k,
            rLen;

        for ( k = 0, rLen = results.length; k < rLen && allTweets.length < options.numberOfTweets; k++ ) {
          allTweets.push( results[ k ] );
        }

        // Search API doesn't simply return count of tweets. It returns up to 100
        // and then provides a link to query the next "Page" of the same results
        if ( allTweets.length < options.numberOfTweets && options.search ) {
          Popcorn.xhr({
            url: requestString.substring( 0, requestString.indexOf( "?" ) ) + e.next_page,
            dataType: "jsonp",
            success: twitterCallback
          });
        } else {
          buildTheTweets( allTweets );
        }
      }

      target.appendChild( options._container );

      // We stored the results objects we get to save API calls being made
      if ( !CACHED_RESULTS[ query ] ) {
        if ( options.username ) {
          Popcorn.xhr({
            url: "https://api.twitter.com/1/account/rate_limit_status.json",
            dataType: "jsonp",
            success: function( e ) {
              if ( e.remaining_hits === 0 ) {
                var warningText = document.createElement( "div" );

                warningText.innerHTML = "You have hit the request limit for the hour. This will reset at " +
                  e.reset_time.substring( 0, e.reset_time.indexOf( "+" ) ) + " GMT.";

                options._container.appendChild( warningText );
              } else {
                // Append various query options here
                requestString += options.username +
                               "&count=" + options.numberOfTweets + "&include_rts=true";

                Popcorn.xhr( { url: requestString, dataType: "jsonp", success: twitterCallback } );
              }
          }});
        } else if ( options.search ) {
          requestString = "http://search.twitter.com/search.json?q=";

          requestString += options.search +
                         "&result_type=" + options.searchType;

          Popcorn.xhr( { url: requestString, dataType: "jsonp", success: twitterCallback } );

        }
      } else {
        buildTheTweets( CACHED_RESULTS[ query ] );
      }

      options.toString = function() {
        return options.username || options.search || options._natives.manifest.options.search[ "default" ];
      };
    },
    start: function( event, options ) {
      if ( options._container ) {
        options._container.classList.add( "on" );
        options._container.classList.remove( "off" );
      }
    },
    end: function( event, options ) {
      if ( options._container ) {
        options._container.classList.add( "off" );
        options._container.classList.remove( "on" );
      }
    },
    _teardown: function( options ) {
      // Remove the plugins container when being destroyed
      if ( options._container && options._target ) {
        options._target.removeChild( options._container );
      }
    }
  });
}( Popcorn, this ));
<|endoftext|>


<commit_before>define(function(require) {
    var Backbone = require('Backbone');
    var LifeGameBoard = require('LifeGameBoard');
    var Game = require('Game');
    var _ = require('underscore');

    var EditGameDefinitionForm = Backbone.View.extend({
        el: '#editGameDefinitionForm',

        events: {
            'click .startButton': 'start',
            'click .updateButton': 'update',
            'click .removeButton': 'remove'
        },

        initialize: function() {
            this.$errorMessage = this.$('.message .error');
            this.$successMessage = this.$('.message .success');
            this.$startButton = this.$('.startButton');
            this.$updateButton = this.$('.updateButton');
            this.$removeButton = this.$('.removeButton');
            this.$board = this.$('.board');
        },

        render: function(model) {
            this.model = model;
            this.$errorMessage.text('');
            this.$successMessage.text('');
            this.$board.empty();

            this.model
                .on('request', _.bind(this.controlButton, this, 'lock'))
                .on('error', this.onServerError.bind(this))
                .fetch()
                .done(this.onLoadModel.bind(this));

            return this;
        },

        onLoadModel: function() {
            this.controlButton('fetch-success');

            this.board = new LifeGameBoard({size: this.model.get('size')});

            this.$board.append(this.board.el);

            this.board.on('click-cell', this.onClickCell.bind(this));

            this.board.render(this.model.get('cells'));
        },

        onClickCell: function(position) {
            this.controlButton('changed');
            var size = this.model.get('size');

            if (position.h < size && position.v < size) {
                var cells = this.model.get('cells');
                cells[position.h][position.v] = !cells[position.h][position.v];
                this.board.render(cells);
            }
        },

        start: function() {
            var game = new Game();

            game.register(this.model.id)
                .done(this.trigger.bind(this, 'start-game', game));
        },

        update: function() {
            var self = this;

            this.model
                .update()
                .done(function(response) {
                    self.controlButton('update-success');
                    self.$successMessage.text('更新が完了しました。');
                    self.model.set('version', response.version);
                })
                .fail(function(xhr) {
                    self.onServerError(self, xhr);
                });
        },

        remove: function() {
            var self = this;

            this.model
                .destroy()
                .done(function() {
                    self.controlButton('remove-success');
                    self.$successMessage.text('ゲーム定義を削除しました。');
                    self.$board.empty();
                });
        },

        onServerError: function(model, xhr, options) {
            if (xhr.status === 404) {
                this.$errorMessage.text('ゲーム定義が存在しません。');
            } else if (xhr.status === 409) {
                this.$errorMessage.text('同時更新されています。再検索してください。');
            } else {
                this.$errorMessage.text('サーバーエラーが発生しました。');
            }

            this.controlButton('error');
        },

        controlButton: function(status) {
            if (status === 'error' || status === 'lock' || status === 'remove-success') {
                this.$startButton.attr('disabled', true);
                this.$updateButton.attr('disabled', true);
                this.$removeButton.attr('disabled', true);
            } else if (status === 'update-success' || status === 'fetch-success') {
                this.$startButton.attr('disabled', false);
                this.$updateButton.attr('disabled', true);
                this.$removeButton.attr('disabled', false);
            } else if (status === 'changed') {
                this.$startButton.attr('disabled', true);
                this.$updateButton.attr('disabled', false);
                this.$removeButton.attr('disabled', false);
            }
        }
    });

    return EditGameDefinitionForm;
});<commit_msg>ゲーム開始直前にボタンを非活性に<commit_after>define(function(require) {
    var Backbone = require('Backbone');
    var LifeGameBoard = require('LifeGameBoard');
    var Game = require('Game');
    var _ = require('underscore');

    var EditGameDefinitionForm = Backbone.View.extend({
        el: '#editGameDefinitionForm',

        events: {
            'click .startButton': 'start',
            'click .updateButton': 'update',
            'click .removeButton': 'remove'
        },

        initialize: function() {
            this.$errorMessage = this.$('.message .error');
            this.$successMessage = this.$('.message .success');
            this.$startButton = this.$('.startButton');
            this.$updateButton = this.$('.updateButton');
            this.$removeButton = this.$('.removeButton');
            this.$board = this.$('.board');
        },

        render: function(model) {
            this.model = model;
            this.$errorMessage.text('');
            this.$successMessage.text('');
            this.$board.empty();

            this.model
                .on('request', _.bind(this.controlButton, this, 'lock'))
                .on('error', this.onServerError.bind(this))
                .fetch()
                .done(this.onLoadModel.bind(this));

            return this;
        },

        onLoadModel: function() {
            this.controlButton('fetch-success');

            this.board = new LifeGameBoard({size: this.model.get('size')});

            this.$board.append(this.board.el);

            this.board.on('click-cell', this.onClickCell.bind(this));

            this.board.render(this.model.get('cells'));
        },

        onClickCell: function(position) {
            this.controlButton('changed');
            var size = this.model.get('size');

            if (position.h < size && position.v < size) {
                var cells = this.model.get('cells');
                cells[position.h][position.v] = !cells[position.h][position.v];
                this.board.render(cells);
            }
        },

        start: function() {
            var game = new Game();
            this.controlButton('lock');
            game.register(this.model.id)
                .done(this.trigger.bind(this, 'start-game', game));
        },

        update: function() {
            var self = this;

            this.model
                .update()
                .done(function(response) {
                    self.controlButton('update-success');
                    self.$successMessage.text('更新が完了しました。');
                    self.model.set('version', response.version);
                })
                .fail(function(xhr) {
                    self.onServerError(self, xhr);
                });
        },

        remove: function() {
            var self = this;

            this.model
                .destroy()
                .done(function() {
                    self.controlButton('remove-success');
                    self.$successMessage.text('ゲーム定義を削除しました。');
                    self.$board.empty();
                });
        },

        onServerError: function(model, xhr, options) {
            if (xhr.status === 404) {
                this.$errorMessage.text('ゲーム定義が存在しません。');
            } else if (xhr.status === 409) {
                this.$errorMessage.text('同時更新されています。再検索してください。');
            } else {
                this.$errorMessage.text('サーバーエラーが発生しました。');
            }

            this.controlButton('error');
        },

        controlButton: function(status) {
            if (status === 'error' || status === 'lock' || status === 'remove-success') {
                this.$startButton.attr('disabled', true);
                this.$updateButton.attr('disabled', true);
                this.$removeButton.attr('disabled', true);
            } else if (status === 'update-success' || status === 'fetch-success') {
                this.$startButton.attr('disabled', false);
                this.$updateButton.attr('disabled', true);
                this.$removeButton.attr('disabled', false);
            } else if (status === 'changed') {
                this.$startButton.attr('disabled', true);
                this.$updateButton.attr('disabled', false);
                this.$removeButton.attr('disabled', false);
            }
        }
    });

    return EditGameDefinitionForm;
});<|endoftext|>


<commit_before>import React, { Component } from "react";
import { Chart } from "../components/Chart";
import { connect } from "react-redux";

class ChartContainer extends Component {
  averageLine() {
    if (this.props.progressData) {
      return new Array(this.props.progressData.length).fill(this.props.average);
    }
    return [];
  }

  render() {
    //dummy data
    const options = {
      maintainAspectRatio: true,
      scales: {
        yAxes: [
          {
            ticks: {
              max: this.props.maxPoints,
              min: 0
            }
          }
        ]
      }
    };
    const data = {
      labels: this.props.progressData.map(function(item){return item.day}),
      datasets: [
        {
          label: "Omat pisteet",
          fill: false,
          lineTension: 0.1,
          backgroundColor: "rgba(75,192,192,0.4)",
          borderColor: "rgba(75,192,192,1)",
          borderCapStyle: "butt",
          borderDash: [],
          borderDashOffset: 0.0,
          borderJoinStyle: "miter",
          pointBorderColor: "rgba(75,192,192,1)",
          pointBackgroundColor: "#fff",
          pointBorderWidth: 1,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: "rgba(75,192,192,1)",
          pointHoverBorderColor: "rgba(220,220,220,1)",
          pointHoverBorderWidth: 2,
          pointRadius: 1,
          pointHitRadius: 10,
          data: this.props.progressData.map(function(item){return item.points})
        },
        {
          label: "Kurssin keskiarvo",
          fill: false,
          lineTension: 0.1,
          backgroundColor: "rgba(150,150,150,1)",
          borderColor: "rgba(150,150,150,1)",
          borderCapStyle: "butt",
          //borderDash: [20],
          //borderDashOffset: 0.0,
          borderJoinStyle: "miter",
          pointBackgroundColor: "#fff",
          pointBorderWidth: 0,
          pointHoverRadius: 0,
          pointHoverBackgroundColor: "rgba(75,192,192,1)",
          pointHoverBorderColor: "rgba(220,220,220,1)",
          pointHoverBorderWidth: 0,
          pointRadius: 0,
          pointHitRadius: 0,
          data: this.averageLine()
        }
      ]
    };

    return <Chart data={data} options={options} />;
  }
}

//Connect chart container to it's data in the store

const mapStateToProps = state => {
  return {
    progressLabels: state.APIcalls.progressLabels,
    progressData: state.APIcalls.progressData,
    maxPoints: state.APIcalls.courseMaxPoints,
    average: state.APIcalls.progressAverage
  };
};

export default connect(mapStateToProps, null)(ChartContainer);
<commit_msg>removed dashed border from average label in points chart<commit_after>import React, { Component } from "react";
import { Chart } from "../components/Chart";
import { connect } from "react-redux";

class ChartContainer extends Component {
  averageLine() {
    if (this.props.progressData) {
      return new Array(this.props.progressData.length).fill(this.props.average);
    }
    return [];
  }

  render() {
    //dummy data
    const options = {
      maintainAspectRatio: true,
      scales: {
        yAxes: [
          {
            ticks: {
              max: this.props.maxPoints,
              min: 0
            }
          }
        ]
      }
    };
    const data = {
      labels: this.props.progressData.map(function(item){return item.day}),
      datasets: [
        {
          label: "Omat pisteet",
          fill: false,
          lineTension: 0.1,
          backgroundColor: "rgba(75,192,192,0.4)",
          borderColor: "rgba(75,192,192,1)",
          borderCapStyle: "butt",
          borderDash: [],
          borderDashOffset: 0.0,
          borderJoinStyle: "miter",
          pointBorderColor: "rgba(75,192,192,1)",
          pointBackgroundColor: "#fff",
          pointBorderWidth: 1,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: "rgba(75,192,192,1)",
          pointHoverBorderColor: "rgba(220,220,220,1)",
          pointHoverBorderWidth: 2,
          pointRadius: 1,
          pointHitRadius: 10,
          data: this.props.progressData.map(function(item){return item.points})
        },
        {
          label: "Kurssin keskiarvo",
          fill: false,
          lineTension: 0.1,
          backgroundColor: "rgba(150,150,150,1)",
          borderColor: "rgba(150,150,150,1)",
          borderCapStyle: "butt",
          borderJoinStyle: "miter",
          pointBackgroundColor: "#fff",
          pointBorderWidth: 0,
          pointHoverRadius: 0,
          pointHoverBackgroundColor: "rgba(75,192,192,1)",
          pointHoverBorderColor: "rgba(220,220,220,1)",
          pointHoverBorderWidth: 0,
          pointRadius: 0,
          pointHitRadius: 0,
          data: this.averageLine()
        }
      ]
    };

    return <Chart data={data} options={options} />;
  }
}

//Connect chart container to it's data in the store

const mapStateToProps = state => {
  return {
    progressLabels: state.APIcalls.progressLabels,
    progressData: state.APIcalls.progressData,
    maxPoints: state.APIcalls.courseMaxPoints,
    average: state.APIcalls.progressAverage
  };
};

export default connect(mapStateToProps, null)(ChartContainer);
<|endoftext|>


<commit_before>'use strict';

const Brakes = require('../lib/Brakes');
const Circuit = require('../lib/Circuit');
const expect = require('chai').expect;
const sinon = require('sinon');
const TimeOutError = require('../lib/TimeOutError');
const CircuitBrokenError = require('../lib/CircuitBrokenError');

let brake;

const noop = function noop(foo, err, cb) {
  if (typeof err === 'function') {
    cb = err;
    err = null;
  }
  cb(err ? new Error(err) : null, foo);
};
const nopr = function nopr(foo, err) {
  return new Promise((resolve, reject) => {
    if (err) { reject(new Error(err)); }
    else { resolve(foo); }
  });
};
const slowpr = function slowpr(foo) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(foo);
    }, 50);
  });
};
const fbpr = function fallback(foo, err) {
  return new Promise(resolve => {
    resolve(foo || err);
  });
};
describe('Circuit Class', () => {
  afterEach(() => {
    if (brake instanceof Brakes) {
      brake.destroy();
      brake = undefined;
    }
  });
  it('Should construct with or without fallback and with or without options', () => {
    brake = new Brakes(noop);
    expect(brake).to.be.instanceof(Brakes);
    const circuit1 = new Circuit(brake, noop);
    expect(circuit1).to.be.instanceof(Circuit);
    const circuit2 = new Circuit(brake, noop, noop);
    expect(circuit2).to.be.instanceof(Circuit);
    const circuit3 = new Circuit(brake, noop, { timeout: 10 });
    expect(circuit3).to.be.instanceof(Circuit);
    const circuit4 = new Circuit(brake, noop, noop, { timeout: 10 });
    expect(circuit4).to.be.instanceof(Circuit);
  });
  it('Should promisify the service func', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, noop);
    return circuit._serviceCall('test').then(result => {
      expect(result).to.equal('test');
    });
  });
  it('Should promisify and reject service func', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, noop);
    return circuit._serviceCall(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('err');
    });
  });
  it('Should accept a promise', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    return circuit._serviceCall('test').then(result => {
      expect(result).to.equal('test');
    });
  });
  it('Should reject a promise', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    return circuit._serviceCall(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('err');
    });
  });
  it('Throw an error if not passed a Brake', () => {
    expect(() => {
      brake = new Brakes(noop);
      const circuit = new Circuit();
      circuit.test();
    }).to.throw();
  });
  it('Throw an error if not passed a Brake and a function', () => {
    expect(() => {
      brake = new Brakes(noop);
      const circuit = new Circuit(brake);
      circuit.test();
    }).to.throw();
  });
  it('Throw an error if not passed a Brake and not a function', () => {
    expect(() => {
      brake = new Brakes(noop);
      const circuit = new Circuit(brake, {});
      circuit.test();
    }).to.throw();
  });
  it('Throw an error if not passed a Brake and fallback not a function', () => {
    expect(() => {
      brake = new Brakes(noop);
      const circuit = new Circuit(brake, noop, {}, {});
      circuit.test();
    }).to.throw();
  });
  it('Should trigger event on exec', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    const spy = sinon.spy(() => {});
    brake.on('exec', spy);
    return circuit.exec('foo').then(result => {
      expect(result).to.equal('foo');
      expect(spy.calledOnce).to.equal(true);
    });
  });
  it('Should Resolve a service call and trigger event', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    const spy = sinon.spy(() => {});
    brake.on('success', spy);
    return circuit.exec('foo').then(result => {
      expect(result).to.equal('foo');
      expect(spy.calledOnce).to.equal(true);
    });
  });
  it('Should Reject a service call and trigger event', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, noop);
    const spy = sinon.spy(() => {});
    brake.on('failure', spy);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('[Breaker: defaultBrake] err');
      expect(spy.calledOnce).to.equal(true);
      expect(spy.getCall(0).args[1]).to.equal(err);
    });
  });
  it('Should timeout a service call and trigger event', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, slowpr, { timeout: 1 });
    const spy = sinon.spy(() => {});
    brake.on('timeout', spy);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(TimeOutError);
      expect(spy.calledOnce).to.equal(true);
      expect(spy.getCall(0).args[1]).to.equal(err);
    });
  });
  it('Should timeout a service call and trigger event (brake override)', () => {
    brake = new Brakes(noop, { timeout: 1 });
    const circuit = new Circuit(brake, slowpr);
    const spy = sinon.spy(() => {});
    brake.on('timeout', spy);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(TimeOutError);
      expect(spy.calledOnce).to.equal(true);
    });
  });
  it('Should call fallback if circuit is broken', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr, fbpr);
    brake._circuitOpen = true;
    return circuit.exec('test').then(result => {
      expect(result).to.equal('test');
    });
  });
  it('Should call master fallback when circuit open if used in a slave context', () => {
    brake = new Brakes({
      fallback: () => Promise.resolve('fallback')
    });
    const circuit = brake.slaveCircuit(nopr);
    brake._circuitOpen = true;
    return circuit.exec('test').then(result => {
      expect(result).to.equal('fallback');
    });
  });
  it('Should call master fallback when request fails if used in a slave context', () => {
    brake = new Brakes({
      fallback: () => Promise.resolve('fallback')
    });
    const circuit = brake.slaveCircuit(nopr);
    return circuit.exec(undefined, 'test').then(result => {
      expect(result).to.equal('fallback');
    });
  });
  it('Fallback should cascade fail', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr, noop);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('err');
    });
  });
  it('Fallback should succeed', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr, fbpr);
    return circuit.exec(null, 'thisShouldFailFirstCall').then(result => {
      expect(result).to.equal('thisShouldFailFirstCall');
    });
  });
  it('Should reject with error if circuit is open and has no fallback', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    brake._circuitOpen = true;
    brake._failureHandler(100);
    return circuit.exec('test').then(null, err => {
      expect(err).to.be.instanceof(CircuitBrokenError);
      expect(err.message).to.equal('[Breaker: defaultBrake] Circuit has been opened - The percentage of failed requests (100%) is greater than the threshold specified (50%)');
    });
  });
  it('Should not count as failure if `isFailure` returns `false`', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, noop, { isFailure: () => false });
    const spy = sinon.spy(() => {});
    brake.on('failure', spy);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('[Breaker: defaultBrake] err');
      expect(spy.called).to.equal(false);
    });
  });
});
<commit_msg>fixed broken tests after master merge<commit_after>'use strict';

const Brakes = require('../lib/Brakes');
const Circuit = require('../lib/Circuit');
const expect = require('chai').expect;
const sinon = require('sinon');
const TimeOutError = require('../lib/TimeOutError');
const CircuitBrokenError = require('../lib/CircuitBrokenError');

let brake;

const noop = function noop(foo, err, cb) {
  if (typeof err === 'function') {
    cb = err;
    err = null;
  }
  cb(err ? new Error(err) : null, foo);
};
const nopr = function nopr(foo, err) {
  return new Promise((resolve, reject) => {
    if (err) { reject(new Error(err)); }
    else { resolve(foo); }
  });
};
const slowpr = function slowpr(foo) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(foo);
    }, 50);
  });
};
const fbpr = function fallback(foo, err) {
  return new Promise(resolve => {
    resolve(foo || err);
  });
};
describe('Circuit Class', () => {
  afterEach(() => {
    if (brake instanceof Brakes) {
      brake.destroy();
      brake = undefined;
    }
  });
  it('Should construct with or without fallback and with or without options', () => {
    brake = new Brakes(noop);
    expect(brake).to.be.instanceof(Brakes);
    const circuit1 = new Circuit(brake, noop);
    expect(circuit1).to.be.instanceof(Circuit);
    const circuit2 = new Circuit(brake, noop, noop);
    expect(circuit2).to.be.instanceof(Circuit);
    const circuit3 = new Circuit(brake, noop, { timeout: 10 });
    expect(circuit3).to.be.instanceof(Circuit);
    const circuit4 = new Circuit(brake, noop, noop, { timeout: 10 });
    expect(circuit4).to.be.instanceof(Circuit);
  });
  it('Should promisify the service func', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, noop);
    return circuit._serviceCall('test').then(result => {
      expect(result).to.equal('test');
    });
  });
  it('Should promisify and reject service func', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, noop);
    return circuit._serviceCall(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('err');
    });
  });
  it('Should accept a promise', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    return circuit._serviceCall('test').then(result => {
      expect(result).to.equal('test');
    });
  });
  it('Should reject a promise', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    return circuit._serviceCall(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('err');
    });
  });
  it('Throw an error if not passed a Brake', () => {
    expect(() => {
      brake = new Brakes(noop);
      const circuit = new Circuit();
      circuit.test();
    }).to.throw();
  });
  it('Throw an error if not passed a Brake and a function', () => {
    expect(() => {
      brake = new Brakes(noop);
      const circuit = new Circuit(brake);
      circuit.test();
    }).to.throw();
  });
  it('Throw an error if not passed a Brake and not a function', () => {
    expect(() => {
      brake = new Brakes(noop);
      const circuit = new Circuit(brake, {});
      circuit.test();
    }).to.throw();
  });
  it('Throw an error if not passed a Brake and fallback not a function', () => {
    expect(() => {
      brake = new Brakes(noop);
      const circuit = new Circuit(brake, noop, {}, {});
      circuit.test();
    }).to.throw();
  });
  it('Should trigger event on exec', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    const spy = sinon.spy(() => {});
    brake.on('exec', spy);
    return circuit.exec('foo').then(result => {
      expect(result).to.equal('foo');
      expect(spy.calledOnce).to.equal(true);
    });
  });
  it('Should Resolve a service call and trigger event', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    const spy = sinon.spy(() => {});
    brake.on('success', spy);
    return circuit.exec('foo').then(result => {
      expect(result).to.equal('foo');
      expect(spy.calledOnce).to.equal(true);
    });
  });
  it('Should Reject a service call and trigger event', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, noop);
    const spy = sinon.spy(() => {});
    brake.on('failure', spy);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('[Breaker: defaultBrake] err');
      expect(spy.calledOnce).to.equal(true);
      expect(spy.getCall(0).args[1]).to.equal(err);
    });
  });
  it('Should timeout a service call and trigger event', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, slowpr, { timeout: 1 });
    const spy = sinon.spy(() => {});
    brake.on('timeout', spy);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(TimeOutError);
      expect(spy.calledOnce).to.equal(true);
      expect(spy.getCall(0).args[1]).to.equal(err);
    });
  });
  it('Should timeout a service call and trigger event (brake override)', () => {
    brake = new Brakes(noop, { timeout: 1 });
    const circuit = new Circuit(brake, slowpr);
    const spy = sinon.spy(() => {});
    brake.on('timeout', spy);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(TimeOutError);
      expect(spy.calledOnce).to.equal(true);
    });
  });
  it('Should call fallback if circuit is broken', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr, fbpr);
    brake._circuitOpen = true;
    return circuit.exec('test').then(result => {
      expect(result).to.equal('test');
    });
  });
  it('Should call master fallback when circuit open if used in a slave context', () => {
    brake = new Brakes({
      fallback: () => Promise.resolve('fallback')
    });
    const circuit = brake.slaveCircuit(nopr);
    brake._circuitOpen = true;
    return circuit.exec('test').then(result => {
      expect(result).to.equal('fallback');
    });
  });
  it('Should call master fallback when request fails if used in a slave context', () => {
    brake = new Brakes({
      fallback: () => Promise.resolve('fallback')
    });
    const circuit = brake.slaveCircuit(nopr);
    return circuit.exec(undefined, 'test').then(result => {
      expect(result).to.equal('fallback');
    });
  });
  it('Fallback should cascade fail', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr, noop);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('err');
    });
  });
  it('Fallback should succeed', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr, fbpr);
    return circuit.exec(null, 'thisShouldFailFirstCall').then(result => {
      expect(result).to.equal('thisShouldFailFirstCall');
    });
  });
  it('Should reject with error if circuit is open and has no fallback', () => {
    brake = new Brakes(nopr);
    const circuit = new Circuit(brake, nopr);
    brake._circuitOpen = true;
    brake._failureHandler(100, 1);
    return circuit.exec('test').then(null, err => {
      expect(err).to.be.instanceof(CircuitBrokenError);
      expect(err.message).to.equal('[Breaker: defaultBrake] Circuit has been opened - The percentage of failed requests (100%) is greater than the threshold specified (50%)');
    });
  });
  it('Should not count as failure if `isFailure` returns `false`', () => {
    brake = new Brakes(noop);
    const circuit = new Circuit(brake, noop, { isFailure: () => false });
    const spy = sinon.spy(() => {});
    brake.on('failure', spy);
    return circuit.exec(null, 'err').then(null, err => {
      expect(err).to.be.instanceof(Error);
      expect(err.message).to.equal('[Breaker: defaultBrake] err');
      expect(spy.called).to.equal(false);
    });
  });
});
<|endoftext|>


<commit_before>// Vogue - Client
// Copyright (c) 2011 Andrew Davey (andrew@equin.co.uk)

(function() {

var script = getScriptInfo();

loadScripts({
  io: script.url + 'socket.io/socket.io.js'
}, vogue);

function vogue() {
  var stylesheets = getLocalStylesheets();
  var socket = io.connect("http://" + script.domain + ":" + script.port);
  socket.on('connect', watchAllStylesheets);
  socket.on('update', handleMessage);

  function watchAllStylesheets() {
    for (var href in stylesheets) {
      socket.emit('watch', { href: href });
    }
  }

  function handleMessage(message) {
    reloadStylesheet(message.href);
  }

  function reloadStylesheet(href) {
    var newHref = stylesheets[href].href
      + (href.indexOf('?') >= 0 ? '&' : '?')
      + '_vogue_nocache='
      + (new Date()).getTime();
      stylesheets[href].href = newHref;
  }

  function getLocalStylesheets() {

    function isLocalStylesheet(link) {
      if (link.getAttribute('rel') !== 'stylesheet') {
        return false;
      }
      var href = link.href;
      var isExternal = true;
      for (var i=0; i<script.bases.length; i++) {
        if (href.indexOf(script.bases[i]) > -1) {
          isExternal = false;
          break;
        }
      }
      return !(isExternal && href.match(/^https?:/));
    }

    var links = document.getElementsByTagName('link');
    var stylesheets = {};
    for (var i = 0, m = links.length; i < m; i++) {
      if (!isLocalStylesheet(links[i])) {
        continue;
      }
      // Match hrefs against stylesheet bases we know of
      for (var j=0; j<script.bases.length; j++) {
        if (links[i].href.indexOf(script.bases[j]) > -1) {
          var href = links[i].href.substr(script.bases[j].length);
          stylesheets[href] = links[i];
          break;
        }
      }
    }

    return stylesheets;
  }
}

function loadScripts(scripts, loadedCallback) {
  var srcs = [];
  for (var property in scripts) {
    if (!(property in window)) srcs.push(scripts[property]);
  }

  var count = srcs.length;
  if (count == 0) loadedCallback();
  for (var i = 0; i < srcs.length; i++) {
    var src = srcs[i];
    loadScript(src, function() {
      count--;
      if (count == 0) loadedCallback();
    });
  }
}

function loadScript(src, loadedCallback) {
  var script = document.createElement('script');
  script.setAttribute('type', 'text/javascript');
  script.setAttribute('src', src);
  script.onload = loadedCallback; // Chrome
  script.onreadystatechange = function () { // IE?
    if (this.readyState == 'complete' || this.readyState == 'loaded') loadedCallback();
  };
  document.getElementsByTagName('head')[0].appendChild(script);
}

function getScriptInfo() {
  var bases = [document.location.protocol + '//' + document.location.host];
  if (typeof window.__vogue__ === "undefined") {
    var scripts = document.getElementsByTagName("script");
    var src = scripts[scripts.length - 1].getAttribute("src");

    var url = src.match(/https?\:\/\/.*?\//)[0];

    var domain = src.match(/https?\:\/(.*?)\//)[1];

    var baseMatch = src.match(/\bbase=(.*)(&|$)/);
    if (baseMatch) {
      bases = bases.concat(baseMatch[1].split(','));
    }

    return {
      url: url,
      domain: domain,
      port: getPort(url),
      bases: bases
    };
  } else {
    window.__vogue__.bases = bases;
    return window.__vogue__;
  }
}

function getPort(url) {
  // URL may contain the port number after the second colon.
  // http://domain:1234/
  var index = url.indexOf(':', 6); // skipping 6 characters to ignore first colon
  if (index < 0) return 80; // default to port 80 if none found.
  return parseInt(url.substr(index+1), 10);
}

})();
<commit_msg>Remove duplicate regex match.<commit_after>// Vogue - Client
// Copyright (c) 2011 Andrew Davey (andrew@equin.co.uk)

(function() {

var script = getScriptInfo();

loadScripts({
  io: script.url + 'socket.io/socket.io.js'
}, vogue);

function vogue() {
  var stylesheets = getLocalStylesheets();
  var socket = io.connect("http://" + script.domain + ":" + script.port);
  socket.on('connect', watchAllStylesheets);
  socket.on('update', handleMessage);

  function watchAllStylesheets() {
    for (var href in stylesheets) {
      socket.emit('watch', { href: href });
    }
  }

  function handleMessage(message) {
    reloadStylesheet(message.href);
  }

  function reloadStylesheet(href) {
    var newHref = stylesheets[href].href
      + (href.indexOf('?') >= 0 ? '&' : '?')
      + '_vogue_nocache='
      + (new Date()).getTime();
      stylesheets[href].href = newHref;
  }

  function getLocalStylesheets() {

    function isLocalStylesheet(link) {
      if (link.getAttribute('rel') !== 'stylesheet') {
        return false;
      }
      var href = link.href;
      var isExternal = true;
      for (var i=0; i<script.bases.length; i++) {
        if (href.indexOf(script.bases[i]) > -1) {
          isExternal = false;
          break;
        }
      }
      return !(isExternal && href.match(/^https?:/));
    }

    var links = document.getElementsByTagName('link');
    var stylesheets = {};
    for (var i = 0, m = links.length; i < m; i++) {
      if (!isLocalStylesheet(links[i])) {
        continue;
      }
      // Match hrefs against stylesheet bases we know of
      for (var j=0; j<script.bases.length; j++) {
        if (links[i].href.indexOf(script.bases[j]) > -1) {
          var href = links[i].href.substr(script.bases[j].length);
          stylesheets[href] = links[i];
          break;
        }
      }
    }

    return stylesheets;
  }
}

function loadScripts(scripts, loadedCallback) {
  var srcs = [];
  for (var property in scripts) {
    if (!(property in window)) srcs.push(scripts[property]);
  }

  var count = srcs.length;
  if (count == 0) loadedCallback();
  for (var i = 0; i < srcs.length; i++) {
    var src = srcs[i];
    loadScript(src, function() {
      count--;
      if (count == 0) loadedCallback();
    });
  }
}

function loadScript(src, loadedCallback) {
  var script = document.createElement('script');
  script.setAttribute('type', 'text/javascript');
  script.setAttribute('src', src);
  script.onload = loadedCallback; // Chrome
  script.onreadystatechange = function () { // IE?
    if (this.readyState == 'complete' || this.readyState == 'loaded') loadedCallback();
  };
  document.getElementsByTagName('head')[0].appendChild(script);
}

function getScriptInfo() {
  var bases = [document.location.protocol + '//' + document.location.host];
  if (typeof window.__vogue__ === "undefined") {
    var scripts = document.getElementsByTagName("script");
    var src = scripts[scripts.length - 1].getAttribute("src");

    var rootMatch = src.match(/https?\:\/\/(.*?)\//);
    var url = rootMatch[0];
    var domain = rootMatch[1];

    var baseMatch = src.match(/\bbase=(.*)(&|$)/);
    if (baseMatch) {
      bases = bases.concat(baseMatch[1].split(','));
    }

    return {
      url: url,
      domain: domain,
      port: getPort(url),
      bases: bases
    };
  } else {
    window.__vogue__.bases = bases;
    return window.__vogue__;
  }
}

function getPort(url) {
  // URL may contain the port number after the second colon.
  // http://domain:1234/
  var index = url.indexOf(':', 6); // skipping 6 characters to ignore first colon
  if (index < 0) return 80; // default to port 80 if none found.
  return parseInt(url.substr(index+1), 10);
}

})();
<|endoftext|>


<commit_before>/* BackupRestoreController
 * Lists existing backups and allows creation
 * of new backups.
 */
(function() {
    'use strict';

    controlplane.controller("BackupRestoreController", ["$scope", "$routeParams", "$notification", "$translate", "resourcesFactory", "authService", "$modalService",
    function($scope, $routeParams, $notification, $translate, resourcesFactory, authService, $modalService) {
        // Ensure logged in
        authService.checkLogin($scope);

        // localization messages
        var BACKUP_RUNNING = $translate.instant("backup_running"),
            BACKUP_COMPLETE = $translate.instant("backup_complete"),
            RESTORE_RUNNING = $translate.instant("restore_running"),
            RESTORE_COMPLETE = $translate.instant("restore_complete"),
            ERROR = $translate.instant("error");

        $scope.createBackup = function(){
            $modalService.create({
                template: $translate.instant("confirm_start_backup"),
                model: $scope,
                title: "backup_create",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "backup_create",
                        action: function(){
                            var notification = $notification.create("Backup").updateStatus(BACKUP_RUNNING).show(false);

                            // TODO - when the server switches to broadcast instead of
                            // channel. this can be greatly simplified
                            resourcesFactory.createBackup().success(function checkFirstStatus(){
                                // recursively check if a valid status has been pushed into
                                // the pipe. if not, shake yourself off and try again. try again.
                                resourcesFactory.getBackupStatus().success(function(data){
                                    // no status has been pushed, so check again
                                    if(data.Detail === ""){
                                       checkFirstStatus();

                                    // a valid status has been pushed, so
                                    // start the usual poll cycle
                                    } else {
                                        pollBackupStatus(notification);
                                    }

                                })
                                .error(function(data, status){
                                    backupRestoreError(notification, data.Detail, status);
                                });
                            })
                            .error(function(data, status){
                                backupRestoreError(notification, data.Detail, status);
                            });

                            this.close();
                        }
                    }
                ]
            });
        };

        $scope.restoreBackup = function(filename){
            $modalService.create({
                template: $translate.instant("confirm_start_restore"),
                model: $scope,
                title: "restore",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "restore",
                        classes: "btn-danger",
                        action: function(){
                            var notification = $notification.create("Restore").updateStatus(RESTORE_RUNNING).show(false);

                            // TODO - when the server switches to broadcast instead of
                            // channel. this can be greatly simplified
                            resourcesFactory.restoreBackup(filename).success(function checkFirstStatus(){
                                // recursively check if a valid status has been pushed into
                                // the pipe. if not, shake yourself off and try again. try again.
                                resourcesFactory.getRestoreStatus().success(function(data){
                                    // no status has been pushed, so check again
                                    if(data.Detail === ""){
                                       checkFirstStatus();

                                    // a valid status has been pushed, so
                                    // start the usual poll cycle
                                    } else {
                                        notification.updateStatus(data.Detail);
                                        pollRestoreStatus(notification);
                                    }

                                })
                                .error(function(data, status){
                                    backupRestoreError(notification, data.Detail, status);
                                });
                            })
                            .error(function(data, status){
                                backupRestoreError(notification, data.Detail, status);
                            });

                            this.close();
                        }
                    }
                ]
            });
        };

        function pollBackupStatus(notification){
            resourcesFactory.getBackupStatus().success(function(data){

                if(data.Detail === ""){
                    notification.updateStatus(BACKUP_COMPLETE);
                    notification.success(false);
                    getBackupFiles();
                    return;
                }
                else if (data.Detail !== "timeout"){
                    notification.updateStatus(data.Detail);
                }

                // poll again
                setTimeout(function(){
                    pollBackupStatus(notification);
                }, 1);

            })
            .error(function(data, status){
                backupRestoreError(notification, data.Detail, status);
            });
        }

        function pollRestoreStatus(notification){
            resourcesFactory.getRestoreStatus().success(function(data){

                // all done!
                if(data.Detail === ""){
                    notification.updateStatus(RESTORE_COMPLETE);
                    notification.success(false);
                    return;

                // something neato has happened. lets show it.
                } else if(data.Detail !== "timeout"){
                    notification.updateStatus(data.Detail);
                }

                // poll again
                setTimeout(function(){
                    pollRestoreStatus(notification);
                }, 1);

            })
            .error(function(data, status){
                backupRestoreError(notification, data.Detail, status);
            });

        }

        function backupRestoreError(notification, data, status){
            notification.updateTitle(ERROR +" "+ status);
            notification.updateStatus(data);
            notification.error();
        }

        function getBackupFiles(){
            resourcesFactory.getBackupFiles().success(function(data){
                $scope.backupFiles = data;

                $scope.$emit("ready");
            });
        }

        function init(){
            $scope.name = "backuprestore";
            $scope.params = $routeParams;
            $scope.breadcrumbs = [{ label: 'breadcrumb_backuprestore', itemClass: 'active' }];

            $scope.backupTable = {
                sorting: {
                    full_path: "asc"
                },
                searchColumns: ['full_path']
            };

            //load backup files
            getBackupFiles();

            // poll for backup files
            resourcesFactory.registerPoll("running", getBackupFiles, 5000);
        }

        init();

        $scope.$on("$destroy", function(){
            resourcesFactory.unregisterAllPolls();
        });
    }]);
})();
<commit_msg>Reduce backup/restore polling frequency to 1/sec<commit_after>/* BackupRestoreController
 * Lists existing backups and allows creation
 * of new backups.
 */
(function() {
    'use strict';

    controlplane.controller("BackupRestoreController", ["$scope", "$routeParams", "$notification", "$translate", "resourcesFactory", "authService", "$modalService",
    function($scope, $routeParams, $notification, $translate, resourcesFactory, authService, $modalService) {
        // Ensure logged in
        authService.checkLogin($scope);

        // localization messages
        var BACKUP_RUNNING = $translate.instant("backup_running"),
            BACKUP_COMPLETE = $translate.instant("backup_complete"),
            RESTORE_RUNNING = $translate.instant("restore_running"),
            RESTORE_COMPLETE = $translate.instant("restore_complete"),
            ERROR = $translate.instant("error");

        $scope.createBackup = function(){
            $modalService.create({
                template: $translate.instant("confirm_start_backup"),
                model: $scope,
                title: "backup_create",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "backup_create",
                        action: function(){
                            var notification = $notification.create("Backup").updateStatus(BACKUP_RUNNING).show(false);

                            // TODO - when the server switches to broadcast instead of
                            // channel. this can be greatly simplified
                            resourcesFactory.createBackup().success(function checkFirstStatus(){
                                // recursively check if a valid status has been pushed into
                                // the pipe. if not, shake yourself off and try again. try again.
                                resourcesFactory.getBackupStatus().success(function(data){
                                    // no status has been pushed, so check again
                                    if(data.Detail === ""){
                                       checkFirstStatus();

                                    // a valid status has been pushed, so
                                    // start the usual poll cycle
                                    } else {
                                        pollBackupStatus(notification);
                                    }

                                })
                                .error(function(data, status){
                                    backupRestoreError(notification, data.Detail, status);
                                });
                            })
                            .error(function(data, status){
                                backupRestoreError(notification, data.Detail, status);
                            });

                            this.close();
                        }
                    }
                ]
            });
        };

        $scope.restoreBackup = function(filename){
            $modalService.create({
                template: $translate.instant("confirm_start_restore"),
                model: $scope,
                title: "restore",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "restore",
                        classes: "btn-danger",
                        action: function(){
                            var notification = $notification.create("Restore").updateStatus(RESTORE_RUNNING).show(false);

                            // TODO - when the server switches to broadcast instead of
                            // channel. this can be greatly simplified
                            resourcesFactory.restoreBackup(filename).success(function checkFirstStatus(){
                                // recursively check if a valid status has been pushed into
                                // the pipe. if not, shake yourself off and try again. try again.
                                resourcesFactory.getRestoreStatus().success(function(data){
                                    // no status has been pushed, so check again
                                    if(data.Detail === ""){
                                       checkFirstStatus();

                                    // a valid status has been pushed, so
                                    // start the usual poll cycle
                                    } else {
                                        notification.updateStatus(data.Detail);
                                        pollRestoreStatus(notification);
                                    }

                                })
                                .error(function(data, status){
                                    backupRestoreError(notification, data.Detail, status);
                                });
                            })
                            .error(function(data, status){
                                backupRestoreError(notification, data.Detail, status);
                            });

                            this.close();
                        }
                    }
                ]
            });
        };

        function pollBackupStatus(notification){
            resourcesFactory.getBackupStatus().success(function(data){

                if(data.Detail === ""){
                    notification.updateStatus(BACKUP_COMPLETE);
                    notification.success(false);
                    getBackupFiles();
                    return;
                }
                else if (data.Detail !== "timeout"){
                    notification.updateStatus(data.Detail);
                }

                // poll again
                setTimeout(function(){
                    pollBackupStatus(notification);
                }, 1000);

            })
            .error(function(data, status){
                backupRestoreError(notification, data.Detail, status);
            });
        }

        function pollRestoreStatus(notification){
            resourcesFactory.getRestoreStatus().success(function(data){

                // all done!
                if(data.Detail === ""){
                    notification.updateStatus(RESTORE_COMPLETE);
                    notification.success(false);
                    return;

                // something neato has happened. lets show it.
                } else if(data.Detail !== "timeout"){
                    notification.updateStatus(data.Detail);
                }

                // poll again
                setTimeout(function(){
                    pollRestoreStatus(notification);
                }, 1000);

            })
            .error(function(data, status){
                backupRestoreError(notification, data.Detail, status);
            });

        }

        function backupRestoreError(notification, data, status){
            notification.updateTitle(ERROR +" "+ status);
            notification.updateStatus(data);
            notification.error();
        }

        function getBackupFiles(){
            resourcesFactory.getBackupFiles().success(function(data){
                $scope.backupFiles = data;

                $scope.$emit("ready");
            });
        }

        function init(){
            $scope.name = "backuprestore";
            $scope.params = $routeParams;
            $scope.breadcrumbs = [{ label: 'breadcrumb_backuprestore', itemClass: 'active' }];

            $scope.backupTable = {
                sorting: {
                    full_path: "asc"
                },
                searchColumns: ['full_path']
            };

            //load backup files
            getBackupFiles();

            // poll for backup files
            resourcesFactory.registerPoll("running", getBackupFiles, 5000);
        }

        init();

        $scope.$on("$destroy", function(){
            resourcesFactory.unregisterAllPolls();
        });
    }]);
})();
<|endoftext|>


<commit_before>'use strict';

function create_gates(new_gates){
    new_gates = new_gates || [{}];
    for(var gate in new_gates){
        gates.push({
          'color': new_gates[gate]['color'] || '#fff',
          'destroy': new_gates[gate]['destroy'] !== void 0
            ? new_gates[gate]['destroy']
            : false,
          'dx': new_gates[gate]['dx'] || false,
          'dy': new_gates[gate]['dy'] || false,
          'event': new_gates[gate]['event'] || function(){},
          'height': new_gates[gate]['height'] || 40,
          'interval': new_gates[gate]['interval'] || 0,
          'x': new_gates[gate]['x'] || 0,
          'y': new_gates[gate]['y'] || 0,
          'width': new_gates[gate]['width'] || 40,
        });
    }
}

function create_particles(new_particles){
    if(particles.length >= core_storage_data['max-particles']){
        return;
    }

    new_particles = new_particles || [{}];
    for(var particle in new_particles){
        particles.push({
          'dx': new_particles[particle]['dx'] || 0,
          'dy': new_particles[particle]['dy'] || 0,
          'height': new_particles[particle]['height'] || core_storage_data['particle-height'],
          'width': new_particles[particle]['width'] || core_storage_data['particle-width'],
          'x': new_particles[particle]['x'] || 0,
          'y': new_particles[particle]['y'] || 0,
        });
    }
}

function draw_logic(){
    canvas_buffer.save();
    canvas_buffer.translate(
      canvas_x - camera_x,
      canvas_y - camera_y
    );

    // Draw background.
    canvas_buffer.fillStyle = '#111';
    canvas_buffer.fillRect(
      boundaries['x'],
      boundaries['y'],
      boundaries['width'],
      boundaries['height']
    );

    // Draw gates.
    for(var gate in gates){
        canvas_buffer.fillStyle = gates[gate]['color'];
        canvas_buffer.fillRect(
          gates[gate]['x'],
          gates[gate]['y'],
          gates[gate]['width'],
          gates[gate]['height']
       );
    }

    // Draw particles.
    canvas_buffer.fillStyle = '#fff';
    for(var particle in particles){
        canvas_buffer.fillRect(
          particles[particle]['x'],
          particles[particle]['y'],
          particles[particle]['width'],
          particles[particle]['height']
        );
    };

    canvas_buffer.restore();

    canvas_buffer.fillStyle = '#fff';
    // Draw camera position.
    canvas_buffer.fillText(
      camera_x + 'x ' + camera_y + 'y',
      5,
      25
    );

    // Draw number of particles
    //   and max-particles.
    canvas_buffer.fillText(
      particles.length
        + '/'
        + core_storage_data['max-particles'],
      5,
      50
    );
}

function logic(){
    // Move camera down.
    if(key_down
      && camera_y < boundaries['y'] + boundaries['height']){
        camera_y += core_storage_data['scroll-speed'];
    }

    // Move camera left.
    if(key_left
      && camera_x > boundaries['x']){
        camera_x -= core_storage_data['scroll-speed'];
    }

    // Move camera right.
    if(key_right
      && camera_x < boundaries['x'] + boundaries['width']){
        camera_x += core_storage_data['scroll-speed'];
    }

    // Move camera up.
    if(key_up
      && camera_y > boundaries['y']){
        camera_y -= core_storage_data['scroll-speed'];
    }

    frame_counter += 1;
    if(frame_counter > 99){
        frame_counter = 0;
    }

    for(var particle in particles){
        particles[particle]['x'] += particles[particle]['dx'];
        particles[particle]['y'] += particles[particle]['dy'];

        if(!math_rectangle_overlap({
          'h0': particles[particle]['height'],
          'h1': boundaries['height'],
          'w0': particles[particle]['width'],
          'w1': boundaries['width'],
          'x0': particles[particle]['x'],
          'x1': boundaries['x'],
          'y0': particles[particle]['y'],
          'y1': boundaries['y'],
        })){
            particles.splice(
              particle,
              1
            );
        }
    }

    for(var gate in gates){
        if(gates[gate]['interval'] > 0
          && frame_counter % gates[gate]['interval'] === 0){
            gates[gate]['event']();
        }

        for(var particle in particles){
            if(math_rectangle_overlap({
              'h0': particles[particle]['height'],
              'h1': gates[gate]['height'],
              'w0': particles[particle]['width'],
              'w1': gates[gate]['width'],
              'x0': particles[particle]['x'],
              'x1': gates[gate]['x'],
              'y0': particles[particle]['y'],
              'y1': gates[gate]['y'],
            })){
                if(gates[gate]['destroy']){
                    particles.splice(
                      particle,
                      1
                    );
                    continue;
                }

                if(gates[gate]['dx'] !== false){
                    particles[particle]['dx'] = gates[gate]['dx'];
                }
                if(gates[gate]['dy'] !== false){
                    particles[particle]['dy'] = gates[gate]['dy'];
                }
            }
        }
    }
}

function setmode_logic(newgame){
    gates = [];
    particles = [];

    // Main menu mode.
    if(canvas_mode === 0){
        document.body.innerHTML = '

Test Level

'
          + '

<input disabled value=ESC>Menu
'
          + '<input id=movement-keys maxlength=4>Camera ↑←↓→
'
          + '<input id=reset-camera-key maxlength=1>Reset Camera

'
          + '
<input id=audio-volume max=1 min=0 step=0.01 type=range>Audio
'
          + '<input id=max-particles>Max Particles
'
          + '<input id=ms-per-frame>ms/Frame
'
          + '<input id=particle-height>Particle Height
'
          + '<input id=particle-width>Particle Width
'
          + '<input id=scroll-speed>Scroll Speed
'
          + 'Reset Settings

';
        core_storage_update();

    // New game mode.
    }else{
        if(newgame){
            core_storage_save();
        }

        camera_x = 0;
        camera_y = 0;
        frame_counter = 0;
        key_left = false;
        key_right = false;
    }
}

var boundaries = {};
var camera_x = 0;
var camera_y = 0;
var drag = false;
var drag_x = 0;
var drag_y = 0;
var frame_counter = 0;
var gates = [];
var key_down = false;
var key_left = false;
var key_right = false;
var key_up = false;
var particles = [];

window.onload = function(){
    core_storage_init({
      'data': {
        'audio-volume': 1,
        'movement-keys': 'WASD',
        'max-particles': 1000,
        'ms-per-frame': 25,
        'particle-height': 5,
        'particle-width': 5,
        'reset-camera-key': 'H',
        'scroll-speed': 5,
      },
      'prefix': 'ParticleRun-2D.htm-',
    });
    canvas_init();

    window.onkeydown = function(e){
        if(canvas_mode <= 0){
            return;
        }

        var key = e.keyCode || e.which;

        // ESC: menu.
        if(key === 27){
            core_menu_toggle();
            return;
        }

        key = String.fromCharCode(key);

        if(key === core_storage_data['movement-keys'][0]){
            key_up = true;

        }else if(key === core_storage_data['movement-keys'][1]){
            key_left = true;

        }else if(key === core_storage_data['movement-keys'][2]){
            key_down = true;

        }else if(key === core_storage_data['movement-keys'][3]){
            key_right = true;

        }else if(key === core_storage_data['reset-camera-key']){
            camera_x = 0;
            camera_y = 0;

        }else if(key === 'Q'){
            canvas_menu_quit();
        }
    };

    window.onkeyup = function(e){
        var key = String.fromCharCode(e.keyCode || e.which);

        if(key === core_storage_data['movement-keys'][0]){
            key_up = false;

        }else if(key === core_storage_data['movement-keys'][1]){
            key_left = false;

        }else if(key === core_storage_data['movement-keys'][2]){
            key_down = false;

        }else if(key === core_storage_data['movement-keys'][3]){
            key_right = false;
        }
    };

    window.onmousedown =
      window.ontouchstart = function(e){
        drag = true;
        drag_x = e.pageX;
        drag_y = e.pageY;
    };

    window.onmousemove =
      window.ontouchmove = function(e){
        if(!drag){
            return;
        }

        camera_x += drag_x - e.pageX;
        camera_y += drag_y - e.pageY;
        drag_x = e.pageX;
        drag_y = e.pageY;
    };

    window.onmouseup =
      window.ontouchend = function(e){
        drag = false;
    };
};
<commit_msg>added core_init(), repo_init(), and began global inputs<commit_after>'use strict';

function create_gates(new_gates){
    new_gates = new_gates || [{}];
    for(var gate in new_gates){
        gates.push({
          'color': new_gates[gate]['color'] || '#fff',
          'destroy': new_gates[gate]['destroy'] !== void 0
            ? new_gates[gate]['destroy']
            : false,
          'dx': new_gates[gate]['dx'] || false,
          'dy': new_gates[gate]['dy'] || false,
          'event': new_gates[gate]['event'] || function(){},
          'height': new_gates[gate]['height'] || 40,
          'interval': new_gates[gate]['interval'] || 0,
          'x': new_gates[gate]['x'] || 0,
          'y': new_gates[gate]['y'] || 0,
          'width': new_gates[gate]['width'] || 40,
        });
    }
}

function create_particles(new_particles){
    if(particles.length >= core_storage_data['max-particles']){
        return;
    }

    new_particles = new_particles || [{}];
    for(var particle in new_particles){
        particles.push({
          'dx': new_particles[particle]['dx'] || 0,
          'dy': new_particles[particle]['dy'] || 0,
          'height': new_particles[particle]['height'] || core_storage_data['particle-height'],
          'width': new_particles[particle]['width'] || core_storage_data['particle-width'],
          'x': new_particles[particle]['x'] || 0,
          'y': new_particles[particle]['y'] || 0,
        });
    }
}

function draw_logic(){
    canvas_buffer.save();
    canvas_buffer.translate(
      canvas_x - camera_x,
      canvas_y - camera_y
    );

    // Draw background.
    canvas_buffer.fillStyle = '#111';
    canvas_buffer.fillRect(
      boundaries['x'],
      boundaries['y'],
      boundaries['width'],
      boundaries['height']
    );

    // Draw gates.
    for(var gate in gates){
        canvas_buffer.fillStyle = gates[gate]['color'];
        canvas_buffer.fillRect(
          gates[gate]['x'],
          gates[gate]['y'],
          gates[gate]['width'],
          gates[gate]['height']
       );
    }

    // Draw particles.
    canvas_buffer.fillStyle = '#fff';
    for(var particle in particles){
        canvas_buffer.fillRect(
          particles[particle]['x'],
          particles[particle]['y'],
          particles[particle]['width'],
          particles[particle]['height']
        );
    };

    canvas_buffer.restore();

    canvas_buffer.fillStyle = '#fff';
    // Draw camera position.
    canvas_buffer.fillText(
      camera_x + 'x ' + camera_y + 'y',
      5,
      25
    );

    // Draw number of particles
    //   and max-particles.
    canvas_buffer.fillText(
      particles.length
        + '/'
        + core_storage_data['max-particles'],
      5,
      50
    );
}

function logic(){
    // Move camera down.
    if(key_down
      && camera_y < boundaries['y'] + boundaries['height']){
        camera_y += core_storage_data['scroll-speed'];
    }

    // Move camera left.
    if(key_left
      && camera_x > boundaries['x']){
        camera_x -= core_storage_data['scroll-speed'];
    }

    // Move camera right.
    if(key_right
      && camera_x < boundaries['x'] + boundaries['width']){
        camera_x += core_storage_data['scroll-speed'];
    }

    // Move camera up.
    if(key_up
      && camera_y > boundaries['y']){
        camera_y -= core_storage_data['scroll-speed'];
    }

    frame_counter += 1;
    if(frame_counter > 99){
        frame_counter = 0;
    }

    for(var particle in particles){
        particles[particle]['x'] += particles[particle]['dx'];
        particles[particle]['y'] += particles[particle]['dy'];

        if(!math_rectangle_overlap({
          'h0': particles[particle]['height'],
          'h1': boundaries['height'],
          'w0': particles[particle]['width'],
          'w1': boundaries['width'],
          'x0': particles[particle]['x'],
          'x1': boundaries['x'],
          'y0': particles[particle]['y'],
          'y1': boundaries['y'],
        })){
            particles.splice(
              particle,
              1
            );
        }
    }

    for(var gate in gates){
        if(gates[gate]['interval'] > 0
          && frame_counter % gates[gate]['interval'] === 0){
            gates[gate]['event']();
        }

        for(var particle in particles){
            if(math_rectangle_overlap({
              'h0': particles[particle]['height'],
              'h1': gates[gate]['height'],
              'w0': particles[particle]['width'],
              'w1': gates[gate]['width'],
              'x0': particles[particle]['x'],
              'x1': gates[gate]['x'],
              'y0': particles[particle]['y'],
              'y1': gates[gate]['y'],
            })){
                if(gates[gate]['destroy']){
                    particles.splice(
                      particle,
                      1
                    );
                    continue;
                }

                if(gates[gate]['dx'] !== false){
                    particles[particle]['dx'] = gates[gate]['dx'];
                }
                if(gates[gate]['dy'] !== false){
                    particles[particle]['dy'] = gates[gate]['dy'];
                }
            }
        }
    }
}

function repo_init(){
    core_storage_init({
      'data': {
        'audio-volume': 1,
        'movement-keys': 'WASD',
        'max-particles': 1000,
        'ms-per-frame': 25,
        'particle-height': 5,
        'particle-width': 5,
        'reset-camera-key': 'H',
        'scroll-speed': 5,
      },
      'prefix': 'ParticleRun-2D.htm-',
    });
    canvas_init();

    window.onkeydown = function(e){
        if(canvas_mode <= 0){
            return;
        }

        var key = e.keyCode || e.which;

        // ESC: menu.
        if(key === 27){
            core_menu_toggle();
            return;
        }

        key = String.fromCharCode(key);

        if(key === core_storage_data['movement-keys'][0]){
            key_up = true;

        }else if(key === core_storage_data['movement-keys'][1]){
            key_left = true;

        }else if(key === core_storage_data['movement-keys'][2]){
            key_down = true;

        }else if(key === core_storage_data['movement-keys'][3]){
            key_right = true;

        }else if(key === core_storage_data['reset-camera-key']){
            camera_x = 0;
            camera_y = 0;

        }else if(key === 'Q'){
            canvas_menu_quit();
        }
    };

    window.onkeyup = function(e){
        var key = String.fromCharCode(e.keyCode || e.which);

        if(key === core_storage_data['movement-keys'][0]){
            key_up = false;

        }else if(key === core_storage_data['movement-keys'][1]){
            key_left = false;

        }else if(key === core_storage_data['movement-keys'][2]){
            key_down = false;

        }else if(key === core_storage_data['movement-keys'][3]){
            key_right = false;
        }
    };

    window.onmousedown =
      window.ontouchstart = function(e){
        drag = true;
        drag_x = e.pageX;
        drag_y = e.pageY;
    };

    window.onmousemove =
      window.ontouchmove = function(e){
        if(!drag){
            return;
        }

        camera_x += drag_x - e.pageX;
        camera_y += drag_y - e.pageY;
        drag_x = e.pageX;
        drag_y = e.pageY;
    };

    window.onmouseup =
      window.ontouchend = function(e){
        drag = false;
    };
}

function setmode_logic(newgame){
    gates = [];
    particles = [];

    // Main menu mode.
    if(canvas_mode === 0){
        document.body.innerHTML = '

Test Level

'
          + '

<input disabled value=ESC>Menu
'
          + '<input id=movement-keys maxlength=4>Camera ↑←↓→
'
          + '<input id=reset-camera-key maxlength=1>Reset Camera

'
          + '
<input id=audio-volume max=1 min=0 step=0.01 type=range>Audio
'
          + '<input id=max-particles>Max Particles
'
          + '<input id=ms-per-frame>ms/Frame
'
          + '<input id=particle-height>Particle Height
'
          + '<input id=particle-width>Particle Width
'
          + '<input id=scroll-speed>Scroll Speed
'
          + 'Reset Settings

';
        core_storage_update();

    // New game mode.
    }else{
        if(newgame){
            core_storage_save();
        }

        camera_x = 0;
        camera_y = 0;
        frame_counter = 0;
        key_left = false;
        key_right = false;
    }
}

var boundaries = {};
var camera_x = 0;
var camera_y = 0;
var drag = false;
var drag_x = 0;
var drag_y = 0;
var frame_counter = 0;
var gates = [];
var key_down = false;
var key_left = false;
var key_right = false;
var key_up = false;
var particles = [];
<|endoftext|>