<commit_before>var _ = require("lodash");
var path = require("path");
var express = require("express");
var bodyParser = require("body-parser");
var compiler = require("krl-compiler");
var version = require("../package.json").version;
var oauth_server = require("./oauth_server");
var mime = require("mime-types");

var mergeGetPost = function(req){
    //give preference to post body params
    return _.assign({}, req.query, req.body);
};

module.exports = function(pe){

    var app = express();
    app.use(function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        next();
    });
    app.use(express.static(path.resolve(__dirname, "..", "public")));
    app.use(bodyParser.json({type: "application/json"}));
    app.use(bodyParser.urlencoded({limit: "512mb", type: "application/x-www-form-urlencoded", extended: false}));

    var errResp = function(res, err){
        var code = 500;
        if(_.isNumber(err.statusCode)){
            code = err.statusCode;
        }else if(err && err.notFound){
            code = 404;
        }
        res.status(code).json({error: err.message});
    };

    app.use(function(err, req, res, next){
        errResp(res, err);
    });
    app.use(function(req, res, next){ // needed by oauth_server
        req.pe = pe;
        req.errResp = errResp;
        next();
    });

    app.all("/sky/event/:eci/:eid/:domain/:type", function(req, res){
        var event = {
            eci: req.params.eci,
            eid: req.params.eid,
            domain: req.params.domain,
            type: req.params.type,
            attrs: mergeGetPost(req)
        };
        pe.signalEvent(event, function(err, response){
            if(err) return errResp(res, err);
            res.json(response);
        });
    });

    app.all("/sky/cloud/:eci/:rid/:function", function(req, res){
        var funcPart = req.params["function"].split(".");
        var respType = mime.contentType(funcPart[1]);
        var query = {
            eci: req.params.eci,
            rid: req.params.rid,
            name: funcPart[0],
            args: mergeGetPost(req)
        };
        pe.runQuery(query, function(err, data){
            if(err) return errResp(res, err);
            if(_.isFunction(data)){
                data(res);
            }else if(respType&&funcPart[1]!="json"){
                res.header("Content-Type", respType);
                res.end(data);
            }else{
                res.json(data);
            }
        });
    });

    app.get("/authorize", oauth_server.authorize);

    app.post("/approve", oauth_server.approve);

    app.post("/token", oauth_server.token);

    app.post("/new-account", oauth_server.new_account);

    app.post("/login", oauth_server.login);

    app.all("/api/engine-version", function(req, res){
        res.json({"version": version});
    });

    app.all("/api/db-dump", function(req, res){
        pe.dbDump(function(err, db_data){
            if(err) return errResp(res, err);

            if(req.query.legacy){
                _.each(db_data.appvars, function(vars, rid){
                    _.each(vars, function(val, name){
                        _.set(db_data, ["resultset", rid, "vars", name], val);
                    });
                });
                _.each(db_data.entvars, function(by_rid, pico_id){
                    _.each(by_rid, function(vars, rid){
                        _.each(vars, function(val, name){
                            _.set(db_data, ["pico", pico_id, rid, "vars", name], val);
                        });
                    });
                });
                _.each(db_data.channel, function(chan, eci){
                    _.set(db_data, ["pico", chan.pico_id, "channel", eci], chan);
                    _.set(db_data, ["channel", eci, "pico_id"], chan.pico_id);
                });
                _.each(db_data["pico-ruleset"], function(data, pico_id){
                    _.each(data, function(val, rid){
                        _.set(db_data, ["pico", pico_id, "ruleset", rid], val);
                    });
                });
            }

            res.json(db_data);
        });
    });

    app.all("/api/root-eci", function(req, res){
        pe.getRootECI(function(err, root_eci){
            if(err) return errResp(res, err);
            res.json({ok: true, eci: root_eci});
        });
    });

    app.all("/api/pico/:id/new-channel", function(req, res){
        var args = mergeGetPost(req);

        pe.newChannel({
            pico_id: req.params.id,
            name: args.name,
            type: args.type
        }, function(err, new_channel){
            if(err) return errResp(res, err);
            res.json(new_channel);
        });
    });

    app.all("/api/pico/:id/rm-channel/:eci", function(req, res){
        pe.removeChannel(req.params.eci, function(err){
            if(err) return errResp(res, err);
            res.json({ok: true});
        });
    });

    app.all("/api/pico/:id/rm-ruleset/:rid", function(req, res){
        pe.uninstallRuleset(req.params.id, req.params.rid, function(err){
            if(err) return errResp(res, err);
            res.json({ok: true});
        });
    });

    app.all("/api/pico/:id/rm-ent-var/:rid/:var_name", function(req, res){
        pe.removeEntVar(req.params.id, req.params.rid, req.params.var_name, function(err){
            if(err) return errResp(res, err);
            res.json({ok: true});
        });
    });

    app.all("/api/ruleset/compile", function(req, res){
        var args = mergeGetPost(req);

        try{
            res.json({ok: true, code: compiler(args.src).code});
        }catch(err){
            res.status(400).json({ error: err.toString() });
        }
    });

    app.all("/api/ruleset/register", function(req, res){
        var args = mergeGetPost(req);

        var onRegister = function(err, data){
            if(err) return errResp(res, err);
            res.json({ok: true, rid: data.rid, hash: data.hash});
        };
        if(_.isString(args.src)){
            pe.registerRuleset(args.src, {}, onRegister);
        }else if(_.isString(args.url)){
            pe.registerRulesetURL(args.url, onRegister);
        }else{
            errResp(res, new Error("expected `src` or `url`"));
        }
    });

    app.all("/api/ruleset/flush/:rid", function(req, res){
        pe.flushRuleset(req.params.rid, function(err, data){
            if(err) return errResp(res, err);
            console.log("Ruleset successfully flushed: " + data.rid);
            res.json({ok: true, rid: data.rid, hash: data.hash});
        });
    });

    app.all("/api/ruleset/unregister/:rid", function(req, res){
        pe.unregisterRuleset(req.params.rid, function(err){
            if(err) return errResp(res, err);
            res.json({ok: true});
        });
    });

    return app;
};
<commit_msg>adding ent:children to db-dump?legacy<commit_after>var _ = require("lodash");
var path = require("path");
var express = require("express");
var bodyParser = require("body-parser");
var compiler = require("krl-compiler");
var version = require("../package.json").version;
var oauth_server = require("./oauth_server");
var mime = require("mime-types");

var mergeGetPost = function(req){
    //give preference to post body params
    return _.assign({}, req.query, req.body);
};

module.exports = function(pe){

    var app = express();
    app.use(function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        next();
    });
    app.use(express.static(path.resolve(__dirname, "..", "public")));
    app.use(bodyParser.json({type: "application/json"}));
    app.use(bodyParser.urlencoded({limit: "512mb", type: "application/x-www-form-urlencoded", extended: false}));

    var errResp = function(res, err){
        var code = 500;
        if(_.isNumber(err.statusCode)){
            code = err.statusCode;
        }else if(err && err.notFound){
            code = 404;
        }
        res.status(code).json({error: err.message});
    };

    app.use(function(err, req, res, next){
        errResp(res, err);
    });
    app.use(function(req, res, next){ // needed by oauth_server
        req.pe = pe;
        req.errResp = errResp;
        next();
    });

    app.all("/sky/event/:eci/:eid/:domain/:type", function(req, res){
        var event = {
            eci: req.params.eci,
            eid: req.params.eid,
            domain: req.params.domain,
            type: req.params.type,
            attrs: mergeGetPost(req)
        };
        pe.signalEvent(event, function(err, response){
            if(err) return errResp(res, err);
            res.json(response);
        });
    });

    app.all("/sky/cloud/:eci/:rid/:function", function(req, res){
        var funcPart = req.params["function"].split(".");
        var respType = mime.contentType(funcPart[1]);
        var query = {
            eci: req.params.eci,
            rid: req.params.rid,
            name: funcPart[0],
            args: mergeGetPost(req)
        };
        pe.runQuery(query, function(err, data){
            if(err) return errResp(res, err);
            if(_.isFunction(data)){
                data(res);
            }else if(respType&&funcPart[1]!="json"){
                res.header("Content-Type", respType);
                res.end(data);
            }else{
                res.json(data);
            }
        });
    });

    app.get("/authorize", oauth_server.authorize);

    app.post("/approve", oauth_server.approve);

    app.post("/token", oauth_server.token);

    app.post("/new-account", oauth_server.new_account);

    app.post("/login", oauth_server.login);

    app.all("/api/engine-version", function(req, res){
        res.json({"version": version});
    });

    app.all("/api/db-dump", function(req, res){
        pe.dbDump(function(err, db_data){
            if(err) return errResp(res, err);

            if(req.query.legacy){
                _.each(db_data.appvars, function(vars, rid){
                    _.each(vars, function(val, name){
                        _.set(db_data, ["resultset", rid, "vars", name], val);
                    });
                });
                _.each(db_data.entvars, function(by_rid, pico_id){
                    _.each(by_rid, function(vars, rid){
                        _.each(vars, function(val, name){
                            _.set(db_data, ["pico", pico_id, rid, "vars", name], val);
                        });
                    });
                });
                _.each(db_data["pico-children"], function(children, pico_id){
                    _.set(db_data, [
                        "pico",
                        pico_id,
                        "io.picolabs.pico",
                        "vars",
                        "children"
                    ], _.map(children, function(val, id){
                        return {
                            id: id,
                            eci: _.get(db_data, ["pico", id, "admin_eci"]),
                        };
                    }));
                });

                _.each(db_data.channel, function(chan, eci){
                    _.set(db_data, ["pico", chan.pico_id, "channel", eci], chan);
                    _.set(db_data, ["channel", eci, "pico_id"], chan.pico_id);
                });
                _.each(db_data["pico-ruleset"], function(data, pico_id){
                    _.each(data, function(val, rid){
                        _.set(db_data, ["pico", pico_id, "ruleset", rid], val);
                    });
                });
            }

            res.json(db_data);
        });
    });

    app.all("/api/root-eci", function(req, res){
        pe.getRootECI(function(err, root_eci){
            if(err) return errResp(res, err);
            res.json({ok: true, eci: root_eci});
        });
    });

    app.all("/api/pico/:id/new-channel", function(req, res){
        var args = mergeGetPost(req);

        pe.newChannel({
            pico_id: req.params.id,
            name: args.name,
            type: args.type
        }, function(err, new_channel){
            if(err) return errResp(res, err);
            res.json(new_channel);
        });
    });

    app.all("/api/pico/:id/rm-channel/:eci", function(req, res){
        pe.removeChannel(req.params.eci, function(err){
            if(err) return errResp(res, err);
            res.json({ok: true});
        });
    });

    app.all("/api/pico/:id/rm-ruleset/:rid", function(req, res){
        pe.uninstallRuleset(req.params.id, req.params.rid, function(err){
            if(err) return errResp(res, err);
            res.json({ok: true});
        });
    });

    app.all("/api/pico/:id/rm-ent-var/:rid/:var_name", function(req, res){
        pe.removeEntVar(req.params.id, req.params.rid, req.params.var_name, function(err){
            if(err) return errResp(res, err);
            res.json({ok: true});
        });
    });

    app.all("/api/ruleset/compile", function(req, res){
        var args = mergeGetPost(req);

        try{
            res.json({ok: true, code: compiler(args.src).code});
        }catch(err){
            res.status(400).json({ error: err.toString() });
        }
    });

    app.all("/api/ruleset/register", function(req, res){
        var args = mergeGetPost(req);

        var onRegister = function(err, data){
            if(err) return errResp(res, err);
            res.json({ok: true, rid: data.rid, hash: data.hash});
        };
        if(_.isString(args.src)){
            pe.registerRuleset(args.src, {}, onRegister);
        }else if(_.isString(args.url)){
            pe.registerRulesetURL(args.url, onRegister);
        }else{
            errResp(res, new Error("expected `src` or `url`"));
        }
    });

    app.all("/api/ruleset/flush/:rid", function(req, res){
        pe.flushRuleset(req.params.rid, function(err, data){
            if(err) return errResp(res, err);
            console.log("Ruleset successfully flushed: " + data.rid);
            res.json({ok: true, rid: data.rid, hash: data.hash});
        });
    });

    app.all("/api/ruleset/unregister/:rid", function(req, res){
        pe.unregisterRuleset(req.params.rid, function(err){
            if(err) return errResp(res, err);
            res.json({ok: true});
        });
    });

    return app;
};
<|endoftext|>


<commit_before>var helpers = {
	determineArchiveRemoteUrl: function(domain){
		domain = domain.toLowerCase().trim();
		var tld = {
			"bitbucket": ".org",
			"github": ".com"
		}
		return domain + tld[domain];
	},
	excludeFiles: function(exclusions){
		return exclusions.map(function(exclusion){
			return '--exclude "' + exclusion + '"' ;
		}).join(' ');
	}
}
var sh_commands = {
	createGitRepoAndRemotes: function(repo_name, url, archive_info){
		return 'cd repositories/' + repo_name + ' && git init && git remote add origin ' + url + '.git' + (archive_info.enabled) ? this.setArchiveRemote(repo_name, archive_info) : '';
	},
	setArchiveRemote: function(repo_name, archive_info){
		return ' && git remote add archived https://' + helpers.determineArchiveRemoteUrl(archive_info.type) + '/' + archive_info.account_name + '/' + repo_name + '.git';
	},
	fetchLatest: function(repo_name, archive_info){
		return 'cd repositories/' + repo_name + ' && git fetch origin && git checkout origin/master' + (archive_info.enabled) ? pushToArchive() : '';
	},
	pushToArchive: function(){
		return ' && git push origin archived';
	},
	setDeploy: function(repo_name, bucket_name, path, exclusions){
		return 'aws s3 sync '+repo_name+' s3://'+bucket_name+'/'+path+repo_name+'/ ' + helpers.excludeFiles(exclusions)
	}
}

module.exports = sh_commands;<commit_msg>spacing<commit_after>var helpers = {
	determineArchiveRemoteUrl: function(domain){
		domain = domain.toLowerCase().trim();
		var tld = {
			"bitbucket": ".org",
			"github": ".com"
		}
		return domain + tld[domain];
	},
	excludeFiles: function(exclusions){
		return exclusions.map(function(exclusion){
			return '--exclude "' + exclusion + '"';
		}).join(' ');
	}
}
var sh_commands = {
	createGitRepoAndRemotes: function(repo_name, url, archive_info){
		return 'cd repositories/' + repo_name + ' && git init && git remote add origin ' + url + '.git' + (archive_info.enabled) ? this.setArchiveRemote(repo_name, archive_info) : '';
	},
	setArchiveRemote: function(repo_name, archive_info){
		return ' && git remote add archived https://' + helpers.determineArchiveRemoteUrl(archive_info.type) + '/' + archive_info.account_name + '/' + repo_name + '.git';
	},
	fetchLatest: function(repo_name, archive_info){
		return 'cd repositories/' + repo_name + ' && git fetch origin && git checkout origin/master' + (archive_info.enabled) ? pushToArchive() : '';
	},
	pushToArchive: function(){
		return ' && git push origin archived';
	},
	setDeploy: function(repo_name, bucket_name, path, exclusions){
		return 'aws s3 sync '+repo_name+' s3://'+bucket_name+'/'+path+repo_name+'/ ' + helpers.excludeFiles(exclusions)
	}
}

module.exports = sh_commands;<|endoftext|>


<commit_before>//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Draws "square" and "circle" shapes using svg:rect
//------------------------------------------------------------------------------
d3plus.shape.rect = function(vars,selection,enter,exit,transform) {

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // The position and size of each rectangle on enter and exit.
  //----------------------------------------------------------------------------
  function init(nodes) {

    nodes
      .attr("x",0)
      .attr("y",0)
      .attr("width",0)
      .attr("height",0)

  }

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // The position and size of each rectangle on update.
  //----------------------------------------------------------------------------
  function update(nodes,mod) {
    if (!mod) var mod = 0
    nodes
      .attr("x",function(d){
        return (-d.d3plus.width/2)-(mod/2)
      })
      .attr("y",function(d){
        return (-d.d3plus.height/2)-(mod/2)
      })
      .attr("width",function(d){
        return d.d3plus.width+mod
      })
      .attr("height",function(d){
        return d.d3plus.height+mod
      })
      .attr("rx",function(d){
        var rounded = vars.shape.default == "circle"
        return rounded ? (d.d3plus.width+mod)/2 : 0
      })
      .attr("ry",function(d){
        var rounded = vars.shape.default == "circle"
        return rounded ? (d.d3plus.height+mod)/2 : 0
      })
      .attr("shape-rendering",function(d){
        if (vars.shape.default == "square") {
          return vars.style.rendering
        }
        else {
          return "auto"
        }
      })
  }

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "rects" Enter
  //----------------------------------------------------------------------------
  enter.append("rect")
    .attr("class","data")
    .call(init)
    .call(d3plus.shape.style,vars)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "rects" Update
  //----------------------------------------------------------------------------
  selection.selectAll("rect.data")
    .data(function(d) {

      if (vars.labels.default && !d.d3plus.label) {

        d.d3plus_label = {
          "w": 0,
          "h": 0,
          "x": 0,
          "y": 0
        }

        // Square bounds
        if (vars.shape.default == "square") {

          var w = d.d3plus.width-(vars.style.labels.padding*2),
              h = d.d3plus.height-(vars.style.labels.padding*2)

          d.d3plus_share = {
            "w": w,
            "h": h/4,
            "x": 0,
            "y": 0
          }

          d.d3plus_label.w = w
          d.d3plus_label.h = h

        }
        // Circle bounds
        else {
          d.d3plus_label.w = Math.sqrt(Math.pow(d.d3plus.width,2)/2)-(vars.style.labels.padding)
          d.d3plus_label.h = Math.sqrt(Math.pow(d.d3plus.height,2)/2)-(vars.style.labels.padding)
        }

      }
      console.log(d.two,d.d3plus_label.h)
      return [d];
    })
    .transition().duration(vars.style.timing.transitions)
      .call(update)
      .call(d3plus.shape.style,vars)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "rects" Exit
  //----------------------------------------------------------------------------
  exit.selectAll("rect.data")
    .transition().duration(vars.style.timing.transitions)
    .call(init)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Define mouse event shapes
  //----------------------------------------------------------------------------
  var mouses = selection.selectAll("rect.mouse")
    .data(function(d) {
      return !d.d3plus.static ? [d] : [];
    })

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Mouse "rect" enter
  //----------------------------------------------------------------------------
  mouses.enter().append("rect")
    .attr("class","mouse")
    .call(init)
    .attr("opacity",0)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Mouse "rect" update and mouse events
  //----------------------------------------------------------------------------
  mouses
    .data(function(d) {
      return !d.d3plus.static ? [d] : [];
    })
    .on(d3plus.evt.over,function(d){

      if (!vars.frozen) {

        d3.select(this).style("cursor","pointer")

        d3.select(this.parentNode).selectAll(".data")
          .transition().duration(vars.style.timing.mouseevents)
          .attr("opacity",1)

        d3.select(this.parentNode)
          .transition().duration(vars.style.timing.mouseevents)
          .call(transform,true)

      }

    })
    .on(d3plus.evt.out,function(d){

      if (!vars.frozen) {

        d3.select(this.parentNode).selectAll(".data")
          .transition().duration(vars.style.timing.mouseevents)
          .attr("opacity",vars.style.data.opacity)

        d3.select(this.parentNode)
          .transition().duration(vars.style.timing.mouseevents)
          .call(transform)

      }

    })
    .transition().duration(vars.style.timing.transitions)
      .call(update,6)

}
<commit_msg>removed console statement<commit_after>//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Draws "square" and "circle" shapes using svg:rect
//------------------------------------------------------------------------------
d3plus.shape.rect = function(vars,selection,enter,exit,transform) {

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // The position and size of each rectangle on enter and exit.
  //----------------------------------------------------------------------------
  function init(nodes) {

    nodes
      .attr("x",0)
      .attr("y",0)
      .attr("width",0)
      .attr("height",0)

  }

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // The position and size of each rectangle on update.
  //----------------------------------------------------------------------------
  function update(nodes,mod) {
    if (!mod) var mod = 0
    nodes
      .attr("x",function(d){
        return (-d.d3plus.width/2)-(mod/2)
      })
      .attr("y",function(d){
        return (-d.d3plus.height/2)-(mod/2)
      })
      .attr("width",function(d){
        return d.d3plus.width+mod
      })
      .attr("height",function(d){
        return d.d3plus.height+mod
      })
      .attr("rx",function(d){
        var rounded = vars.shape.default == "circle"
        return rounded ? (d.d3plus.width+mod)/2 : 0
      })
      .attr("ry",function(d){
        var rounded = vars.shape.default == "circle"
        return rounded ? (d.d3plus.height+mod)/2 : 0
      })
      .attr("shape-rendering",function(d){
        if (vars.shape.default == "square") {
          return vars.style.rendering
        }
        else {
          return "auto"
        }
      })
  }

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "rects" Enter
  //----------------------------------------------------------------------------
  enter.append("rect")
    .attr("class","data")
    .call(init)
    .call(d3plus.shape.style,vars)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "rects" Update
  //----------------------------------------------------------------------------
  selection.selectAll("rect.data")
    .data(function(d) {

      if (vars.labels.default && !d.d3plus.label) {

        d.d3plus_label = {
          "w": 0,
          "h": 0,
          "x": 0,
          "y": 0
        }

        // Square bounds
        if (vars.shape.default == "square") {

          var w = d.d3plus.width-(vars.style.labels.padding*2),
              h = d.d3plus.height-(vars.style.labels.padding*2)

          d.d3plus_share = {
            "w": w,
            "h": h/4,
            "x": 0,
            "y": 0
          }

          d.d3plus_label.w = w
          d.d3plus_label.h = h

        }
        // Circle bounds
        else {
          d.d3plus_label.w = Math.sqrt(Math.pow(d.d3plus.width,2)/2)-(vars.style.labels.padding)
          d.d3plus_label.h = Math.sqrt(Math.pow(d.d3plus.height,2)/2)-(vars.style.labels.padding)
        }

      }

      return [d];
    })
    .transition().duration(vars.style.timing.transitions)
      .call(update)
      .call(d3plus.shape.style,vars)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "rects" Exit
  //----------------------------------------------------------------------------
  exit.selectAll("rect.data")
    .transition().duration(vars.style.timing.transitions)
    .call(init)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Define mouse event shapes
  //----------------------------------------------------------------------------
  var mouses = selection.selectAll("rect.mouse")
    .data(function(d) {
      return !d.d3plus.static ? [d] : [];
    })

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Mouse "rect" enter
  //----------------------------------------------------------------------------
  mouses.enter().append("rect")
    .attr("class","mouse")
    .call(init)
    .attr("opacity",0)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Mouse "rect" update and mouse events
  //----------------------------------------------------------------------------
  mouses
    .data(function(d) {
      return !d.d3plus.static ? [d] : [];
    })
    .on(d3plus.evt.over,function(d){

      if (!vars.frozen) {

        d3.select(this).style("cursor","pointer")

        d3.select(this.parentNode).selectAll(".data")
          .transition().duration(vars.style.timing.mouseevents)
          .attr("opacity",1)

        d3.select(this.parentNode)
          .transition().duration(vars.style.timing.mouseevents)
          .call(transform,true)

      }

    })
    .on(d3plus.evt.out,function(d){

      if (!vars.frozen) {

        d3.select(this.parentNode).selectAll(".data")
          .transition().duration(vars.style.timing.mouseevents)
          .attr("opacity",vars.style.data.opacity)

        d3.select(this.parentNode)
          .transition().duration(vars.style.timing.mouseevents)
          .call(transform)

      }

    })
    .transition().duration(vars.style.timing.transitions)
      .call(update,6)

}
<|endoftext|>


<commit_before>import React from "react";
import PropTypes from "prop-types";

import {
  Pipeline,
  Values,
  responseUpdatedEvent,
  valuesUpdatedEvent
} from "../../controllers";

import classnames from "../classnames";

const RIGHT_ARROW_KEYCODE = 39;
const TAB_KEYCODE = 9;
const RETURN_KEYCODE = 13;
const ESC_KEYCODE = 27;
const UP_ARROW_KEYCODE = 38;
const DOWN_ARROW_KEYCODE = 40;

class AutocompleteSuggestion extends React.Component {
  /**
   * propTypes
   * @property {string} text Current user input text.
   * @property {string} suggestion Suggestion text of this component.
   * @property {boolean} selected Whether this suggestion is currently selected.
   * @property {Function} submit Submit function when the user clicks the suggestion.
   */
  static get propTypes() {
    return {
      text: PropTypes.string,
      suggestion: PropTypes.string,
      selected: PropTypes.bool,
      submit: PropTypes.func
    };
  }

  onClick = () => {
    this.props.submit(this.props.suggestion);
  };

  render() {
    const { text, suggestion, selected } = this.props;

    let prefix = null;
    let prefixLen = 0;
    if (suggestion.substr(0, text.length) === text) {
      prefix = (

          {text}

      );
      prefixLen = text.length;
    }

    const className = classnames({
      "sj-suggestion": true,
      "sj-suggestion-selected": selected
    });

    return (

        {prefix}
        {suggestion.substr(prefixLen)}

    );
  }
}

const getState = (values, pipeline, qParam, suggestionAmount) => {
  const text = values.get()[qParam] || "";
  if (!text) {
    return { text, completion: "", suggestions: [], selectedPosition: -1 };
  }
  const responseValues = pipeline.getResponse().getValues();
  const completion = text && responseValues ? responseValues[qParam] || "" : "";
  const suggestions = responseValues
    ? (responseValues["q.suggestions"] || "")
        .split(",")
        .filter((s, i) => s.length > 0 && i < suggestionAmount)
    : [];
  return { text, completion, suggestions, selectedPosition: -1 };
};

class AutocompleteDropdown extends React.Component {
  /**
   * propTypes
   * @property {Values} values Values object.
   * @property {Pipeline} pipeline Pipeline object.
   * @property {string} placeholder Placeholder to use.
   * @property {number} suggestionAmount Maximum number of suggestion to show.
   * @property {Function} handleSubmit Submit function to call when a query has been chosen.
   * @property {Function} handleUpdate Update function to call when a query has been modified.
   * @property {string} [qParam="q"] Search parameter.
   * @property {string} [qParam="q.override"] Search parameter.
   * @property {boolean} [autoFocus=false] Whether to focus the input element.
   * @property {boolean} [search=true] Whether to search on text updated.
   * @property {boolean} [showCompletion=true] Whether to show completions or not.
   */
  static get propTypes() {
    return {
      values: PropTypes.instanceOf(Values).isRequired,
      pipeline: PropTypes.instanceOf(Pipeline).isRequired,
      placeholder: PropTypes.string,
      suggestionAmount: PropTypes.number,
      handleSubmit: PropTypes.func,
      handleUpdate: PropTypes.func,
      qParam: PropTypes.string,
      qOverrideParam: PropTypes.string,
      autoFocus: PropTypes.bool,
      search: PropTypes.bool,
      showCompletion: PropTypes.bool
    };
  }

  constructor(props) {
    super(props);

    this.state = getState(
      props.values,
      props.pipeline,
      props.qParam,
      props.suggestionAmount
    );

    this.removeValuesListener = this.props.values.listen(
      valuesUpdatedEvent,
      this.valuesChanged
    );
    this.removeResponseListener = this.props.pipeline.listen(
      responseUpdatedEvent,
      this.valuesChanged
    );
  }

  componentWillUpdate(nextProps) {
    const { values: newValues, pipeline: newPipeline } = nextProps;
    const { values: oldValues, pipeline: oldPipeline } = this.props;
    if (newValues !== oldValues) {
      this.removeValuesListener();
      this.removeValuesListener = newValues.listen(
        valuesUpdatedEvent,
        this.valuesChanged
      );
    }
    if (newPipeline !== oldPipeline) {
      this.removeResponseListener();
      this.removeResponseListener = newPipeline.listen(
        responseUpdatedEvent,
        this.valuesChanged
      );
    }
  }

  componentWillUnmount() {
    this.removeValuesListener();
    this.removeResponseListener();
  }

  valuesChanged = () => {
    const { values, pipeline, qParam, suggestionAmount } = this.props;
    this.setState(getState(values, pipeline, qParam, suggestionAmount));
  };

  setText = text => {
    const { qParam, qOverrideParam, values, pipeline, search } = this.props;
    const textValues = { [qParam]: text, [qOverrideParam]: undefined };
    values.set(textValues);
    if (!search) {
      return;
    }
    if (textValues[qParam]) {
      pipeline.search(values.get());
    } else {
      pipeline.clearResponse(values.get());
    }
  };

  submit = query => {
    this.props.handleSubmit(query);
    this.setState({ text: query, suggestions: [], selectedPosition: -1 });
  };

  handleChange = e => {
    this.setText(e.target.value);
    this.props.handleUpdate(e.target.value);
  };

  handleKeyDown = e => {
    const { handleUpdate } = this.props;
    const { text, completion, suggestions, selectedPosition } = this.state;
    if (e.keyCode === ESC_KEYCODE) {
      if (selectedPosition !== -1) {
        handleUpdate(text);
      }
      this.setState({ suggestions: [], selectedPosition: -1 });
      return;
    }
    if (e.keyCode === RETURN_KEYCODE) {
      if (selectedPosition >= 0) {
        this.submit(suggestions[selectedPosition]);
      } else {
        this.submit(text);
      }
      return;
    }
    if (e.keyCode === UP_ARROW_KEYCODE) {
      e.preventDefault();
      if (selectedPosition >= 0) {
        this.setState({
          selectedPosition: selectedPosition - 1
        });
      }
      return;
    }
    if (e.keyCode === DOWN_ARROW_KEYCODE) {
      e.preventDefault();
      if (selectedPosition < suggestions.length - 1) {
        this.setState({
          selectedPosition: selectedPosition + 1
        });
      }
      return;
    }
    if (e.keyCode === RIGHT_ARROW_KEYCODE || e.keyCode === TAB_KEYCODE) {
      e.preventDefault();
      if (selectedPosition >= 0) {
        this.setText(suggestions[selectedPosition]);
        this.setState({ selectedPosition: -1 });
      } else if (completion) {
        this.setState({ text: completion, suggestions: [] });
      }
    }
  };

  render() {
    const { text, completion, suggestions, selectedPosition } = this.state;
    const { placeholder, autoFocus, showCompletion } = this.props;

    const inputText =
      selectedPosition === -1 ? text : suggestions[selectedPosition];

    return (

          <input
            type="text"
            className="sj-search-bar-completion sj-search-bar-input-common"
            value={
              showCompletion
                ? completion.indexOf(text) === 0 ? completion : text
                : ""
            }
            readOnly
          />
          <input
            type="text"
            className="sj-search-bar-input sj-search-bar-input-common"
            placeholder={placeholder}
            autoFocus={autoFocus}
            value={text}
            onChange={this.handleChange}
            onKeyDown={this.handleKeyDown}
          />
          {suggestions.length > 0
            ?

                {suggestions.map((s, i) =>
                  <AutocompleteSuggestion
                    key={s}
                    suggestion={s}
                    text={text.toLowerCase()}
                    selected={i === selectedPosition}
                    submit={this.submit}
                  >
                    {s}
                  </AutocompleteSuggestion>
                )}

            : null}

    );
  }
}

AutocompleteDropdown.defaultProps = {
  qParam: "q",
  qOverrideParam: "q.override",
  suggestionAmount: 10,
  placeHolder: "Search",
  handleSubmit: () => {},
  handleUpdate: () => {},
  search: true,
  showCompletion: true
};

export default AutocompleteDropdown;
<commit_msg>ui: rename props and reword descriptions on AutocompleteDropdown<commit_after>import React from "react";
import PropTypes from "prop-types";

import {
  Pipeline,
  Values,
  responseUpdatedEvent,
  valuesUpdatedEvent
} from "../../controllers";

import classnames from "../classnames";

const RIGHT_ARROW_KEYCODE = 39;
const TAB_KEYCODE = 9;
const RETURN_KEYCODE = 13;
const ESC_KEYCODE = 27;
const UP_ARROW_KEYCODE = 38;
const DOWN_ARROW_KEYCODE = 40;

class AutocompleteSuggestion extends React.Component {
  /**
   * propTypes
   * @property {string} text Current user input text.
   * @property {string} suggestion Suggestion text of this component.
   * @property {boolean} selected Whether this suggestion is currently selected.
   * @property {Function} submit Submit function when the user clicks the suggestion.
   */
  static get propTypes() {
    return {
      text: PropTypes.string,
      suggestion: PropTypes.string,
      selected: PropTypes.bool,
      submit: PropTypes.func
    };
  }

  onClick = () => {
    this.props.submit(this.props.suggestion);
  };

  render() {
    const { text, suggestion, selected } = this.props;

    let prefix = null;
    let prefixLen = 0;
    if (suggestion.substr(0, text.length) === text) {
      prefix = (

          {text}

      );
      prefixLen = text.length;
    }

    const className = classnames({
      "sj-suggestion": true,
      "sj-suggestion-selected": selected
    });

    return (

        {prefix}
        {suggestion.substr(prefixLen)}

    );
  }
}

const getState = (values, pipeline, qParam, suggestionAmount) => {
  const text = values.get()[qParam] || "";
  if (!text) {
    return { text, completion: "", suggestions: [], selectedPosition: -1 };
  }
  const responseValues = pipeline.getResponse().getValues();
  const completion = text && responseValues ? responseValues[qParam] || "" : "";
  const suggestions = responseValues
    ? (responseValues["q.suggestions"] || "")
        .split(",")
        .filter((s, i) => s.length > 0 && i < suggestionAmount)
    : [];
  return { text, completion, suggestions, selectedPosition: -1 };
};

class AutocompleteDropdown extends React.Component {
  /**
   * propTypes
   * @property {Values} values Values object.
   * @property {Pipeline} pipeline Pipeline object.
   * @property {string} placeholder Placeholder to use.
   * @property {number} suggestionAmount Maximum number of suggestion to show.
   * @property {Function} handleForceSearch Callback function called when a user presses Enter while highlighting a suggestion or clicks a suggestion.
   * @property {Function} handleUpdate Callback function called when the query has been modified.
   * @property {string} [qParam="q"] Search parameter.
   * @property {string} [qParam="q.override"] Search override parameter.
   * @property {boolean} [autoFocus=false] Whether to focus the input element.
   * @property {boolean} [instant=true] Whether to search on text updated.
   * @property {boolean} [showCompletion=true] Whether to show completions inline with the query text.
   */
  static get propTypes() {
    return {
      values: PropTypes.instanceOf(Values).isRequired,
      pipeline: PropTypes.instanceOf(Pipeline).isRequired,
      placeholder: PropTypes.string,
      suggestionAmount: PropTypes.number,
      handleForceSearch: PropTypes.func,
      handleForceSearch: PropTypes.func,
      qParam: PropTypes.string,
      qOverrideParam: PropTypes.string,
      autoFocus: PropTypes.bool,
      instant: PropTypes.bool,
      showCompletion: PropTypes.bool
    };
  }

  constructor(props) {
    super(props);

    this.state = getState(
      props.values,
      props.pipeline,
      props.qParam,
      props.suggestionAmount
    );

    this.removeValuesListener = this.props.values.listen(
      valuesUpdatedEvent,
      this.valuesChanged
    );
    this.removeResponseListener = this.props.pipeline.listen(
      responseUpdatedEvent,
      this.valuesChanged
    );
  }

  componentWillUpdate(nextProps) {
    const { values: newValues, pipeline: newPipeline } = nextProps;
    const { values: oldValues, pipeline: oldPipeline } = this.props;
    if (newValues !== oldValues) {
      this.removeValuesListener();
      this.removeValuesListener = newValues.listen(
        valuesUpdatedEvent,
        this.valuesChanged
      );
    }
    if (newPipeline !== oldPipeline) {
      this.removeResponseListener();
      this.removeResponseListener = newPipeline.listen(
        responseUpdatedEvent,
        this.valuesChanged
      );
    }
  }

  componentWillUnmount() {
    this.removeValuesListener();
    this.removeResponseListener();
  }

  valuesChanged = () => {
    const { values, pipeline, qParam, suggestionAmount } = this.props;
    this.setState(getState(values, pipeline, qParam, suggestionAmount));
  };

  setText = text => {
    const { qParam, qOverrideParam, values, pipeline, instant } = this.props;
    const textValues = { [qParam]: text, [qOverrideParam]: undefined };
    values.set(textValues);
    if (!instant) {
      return;
    }
    if (textValues[qParam]) {
      pipeline.search(values.get());
    } else {
      pipeline.clearResponse(values.get());
    }
  };

  submit = query => {
    this.props.handleForceSearch(query);
    this.setState({ text: query, suggestions: [], selectedPosition: -1 });
  };

  handleChange = e => {
    this.setText(e.target.value);
    this.props.handleUpdate(e.target.value);
  };

  handleKeyDown = e => {
    const { handleUpdate } = this.props;
    const { text, completion, suggestions, selectedPosition } = this.state;
    if (e.keyCode === ESC_KEYCODE) {
      if (selectedPosition !== -1) {
        handleUpdate(text);
      }
      this.setState({ suggestions: [], selectedPosition: -1 });
      return;
    }
    if (e.keyCode === RETURN_KEYCODE) {
      if (selectedPosition >= 0) {
        this.submit(suggestions[selectedPosition]);
      } else {
        this.submit(text);
      }
      return;
    }
    if (e.keyCode === UP_ARROW_KEYCODE) {
      e.preventDefault();
      if (selectedPosition >= 0) {
        this.setState({
          selectedPosition: selectedPosition - 1
        });
      }
      return;
    }
    if (e.keyCode === DOWN_ARROW_KEYCODE) {
      e.preventDefault();
      if (selectedPosition < suggestions.length - 1) {
        this.setState({
          selectedPosition: selectedPosition + 1
        });
      }
      return;
    }
    if (e.keyCode === RIGHT_ARROW_KEYCODE || e.keyCode === TAB_KEYCODE) {
      e.preventDefault();
      if (selectedPosition >= 0) {
        this.setText(suggestions[selectedPosition]);
        this.setState({ selectedPosition: -1 });
      } else if (completion) {
        this.setState({ text: completion, suggestions: [] });
      }
    }
  };

  render() {
    const { text, completion, suggestions, selectedPosition } = this.state;
    const { placeholder, autoFocus, showCompletion } = this.props;

    const inputText =
      selectedPosition === -1 ? text : suggestions[selectedPosition];

    return (

          <input
            type="text"
            className="sj-search-bar-completion sj-search-bar-input-common"
            value={
              showCompletion
                ? completion.indexOf(text) === 0 ? completion : text
                : ""
            }
            readOnly
          />
          <input
            type="text"
            className="sj-search-bar-input sj-search-bar-input-common"
            placeholder={placeholder}
            autoFocus={autoFocus}
            value={text}
            onChange={this.handleChange}
            onKeyDown={this.handleKeyDown}
          />
          {suggestions.length > 0
            ?

                {suggestions.map((s, i) =>
                  <AutocompleteSuggestion
                    key={s}
                    suggestion={s}
                    text={text.toLowerCase()}
                    selected={i === selectedPosition}
                    submit={this.submit}
                  >
                    {s}
                  </AutocompleteSuggestion>
                )}

            : null}

    );
  }
}

AutocompleteDropdown.defaultProps = {
  qParam: "q",
  qOverrideParam: "q.override",
  suggestionAmount: 10,
  placeHolder: "Search",
  handleForceSearch: () => {},
  handleUpdate: () => {},
  instant: true,
  showCompletion: true
};

export default AutocompleteDropdown;
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var express = require('express');
var app = express();
var controllers = require('./controllers');
var errorHandler = require('./expressErrorHandler.js');

var port = conf('PORT');
var debug = conf('BUILD_DISTRIBUTION') === 'debug';

logger.info('executing:', process.argv.join(' '));
logger.info('environment: %s, distribution: %s, build: %s',
    conf('NODE_ENV'), conf('BUILD_DISTRIBUTION'), conf('BUILD_VERSION')
);

controllers.load(app, function(){
    app.locals.settings['x-powered-by'] = false;

    if (debug) {
        app.use(express.logger({
            format: ':method :url :status',
            stream: logger.stream('debug')
        }));
    }

    app.use(express.compress());
    app.use(express.bodyParser());

    app.use(app.router);

    if (debug) {
        app.use(express.static('bin/public'));
        app.use(express.favicon('bin/public/favicon.ico'));
    } else {
        logger.info('assuming nginx serves static assets');
    }

    errorHandler.setup(app);

    app.listen(port, function(){
        logger.info('express listening on port', port);
    });
});
<commit_msg>rm path<commit_after>'use strict';

var express = require('express');
var app = express();
var controllers = require('./controllers');
var errorHandler = require('./expressErrorHandler.js');

var port = conf('PORT');
var debug = conf('BUILD_DISTRIBUTION') === 'debug';

logger.info('executing:', process.argv.join(' '));
logger.info('environment: %s, distribution: %s, build: %s',
    conf('NODE_ENV'), conf('BUILD_DISTRIBUTION'), conf('BUILD_VERSION')
);

controllers.load(app, function(){
    app.locals.settings['x-powered-by'] = false;

    if (debug) {
        app.use(express.logger({
            format: ':method :url :status',
            stream: logger.stream('debug')
        }));
    }

    app.use(express.compress());
    app.use(express.bodyParser());

    app.use(app.router);

    if (debug) {
        app.use(express.static('bin/public'));
        app.use(express.favicon('bin/public/favicon.ico'));
    } else {
        logger.info('assuming nginx serves static assets');
    }

    errorHandler.setup(app);

    app.listen(port, function(){
        logger.info('express listening on port', port);
    });
});
<|endoftext|>


<commit_before>/* globals __DEV__ */
import Phaser from 'phaser'
import Mushroom from '../sprites/Mushroom'
import AnimePotato from '../sprites/AnimePotato'

const playerScale = 1
let speed = 2
const walkVelocity = 150

export default class extends Phaser.State {
  // do not know why I needed to add these manually for animation support...
  init () {
  }

  preload () {}

  create () {
    const bannerText = 'Phaser + ES6 + Webpack'
    let banner = this.add.text(this.world.centerX, this.game.height - 80, bannerText)
    banner.font = 'Bangers'
    banner.padding.set(10, 16)
    banner.fontSize = 40
    banner.fill = '#77BFA3'
    banner.smoothed = false
    banner.anchor.setTo(0.5)

    this.explosion = this.game.add.audio('explosion')

    this.mushroom = new Mushroom({
      game: this.game,
      x: this.world.centerX,
      y: this.world.centerY,
      asset: 'mushroom'
    })

    this.player = new AnimePotato({
      game: this.game,
      x: this.world.centerX,
      y: this.world.centerY,
      asset: 'a-potato'
      // scale : {
      //   x: playerScale,
      //   y: playerScale
      // }
    })

    this.game.add.existing(this.mushroom)
    this.game.add.existing(this.player)

    this.game.physics.startSystem(Phaser.Physics.ARCADE)
    this.game.physics.enable([this.player, this.mushroom])

    this.player.animations.add('cycle')
    this.player.scale = {
      x: playerScale,
      y: playerScale
    }
    this.player.body.onCollide = new Phaser.Signal()
    this.player.body.onCollide.add((sprite1, sprite2) => {
      // this.player.animations.play('cycle', 10)
    })

    this.cursors = this.game.input.keyboard.createCursorKeys()
    // face1.body.velocity.setTo(200, 200);
    // face1.body.bounce.set(1);
    //
    // face2.body.velocity.setTo(-200, 200);
    // face2.body.bounce.set(1);
    //
    // face1.body.collideWorldBounds = true;
    // face2.body.collideWorldBounds = true;
  }

  update () {
    const {player} = this
    const {body, scale} = player
    const {velocity} = body
    const {up, down, left, right} = this.cursors
    const {x, y} = velocity
    const slideFriction = 5
    let isWalking = false

    if (up.isDown) {
      velocity.y = -walkVelocity
      isWalking = true
    }
    if (down.isDown) {
      velocity.y = walkVelocity
      isWalking = true
    }
    if (left.isDown) {
      velocity.x = -walkVelocity
      isWalking = true
      scale.x = -1
    }
    if (right.isDown) {
      velocity.x = walkVelocity
      isWalking = true
      scale.x = 1
    }
    if (down.isUp && up.isUp) {
      if (y > 0) {
        velocity.y -= slideFriction
        if (y < 0) velocity.y = 0
      }
      if (y < 0) {
        velocity.y += slideFriction
        if (y > 0) velocity.y = 0
      }
    }
    if (left.isUp && right.isUp) {
      if (x > 0) {
        velocity.x -= slideFriction
        if (x < 0) velocity.x = 0
      }
      if (x < 0) {
        velocity.x += slideFriction
        if (x > 0) velocity.x = 0
      }
    }
    if (isWalking) {
      this.player.animations.play('cycle', 8)
    } else {
      this.player.frame = 0
      this.player.animations.stop()
      // if (x > 0) {
      //   velocity.x -= slideFriction
      //   if (x < 0) velocity.x = 0
      // }
      // if (x < 0) {
      //   velocity.x += slideFriction
      //   if (x > 0) velocity.x = 0
      // }
      // if (y > 0) {
      //   velocity.y -= slideFriction
      //   if (y < 0) velocity.y = 0
      // }
      // if (y < 0) {
      //   velocity.y += slideFriction
      //   if (y > 0) velocity.y = 0
      // }
    }

    this.game.physics.arcade.collide(this.player, this.mushroom, (sprite1, sprite2) => {
      // console.log(sprite1, sprite2)
    })
  }

  render () {
    if (__DEV__) {
      this.game.debug.bodyInfo(this.player, 16, 24)
      // this.game.debug.spriteInfo(this.mushroom, 32, 32)
    }
  }
}
<commit_msg>cleaned up code<commit_after>/* globals __DEV__ */
import Phaser from 'phaser'
import Mushroom from '../sprites/Mushroom'
import AnimePotato from '../sprites/AnimePotato'

const playerScale = 1
let speed = 2
const walkVelocity = 150

export default class extends Phaser.State {
  // do not know why I needed to add these manually for animation support...
  init () {
  }

  preload () {}

  create () {
    const bannerText = 'Phaser + ES6 + Webpack'
    let banner = this.add.text(this.world.centerX, this.game.height - 80, bannerText)
    banner.font = 'Bangers'
    banner.padding.set(10, 16)
    banner.fontSize = 40
    banner.fill = '#77BFA3'
    banner.smoothed = false
    banner.anchor.setTo(0.5)

    this.explosion = this.game.add.audio('explosion')

    this.mushroom = new Mushroom({
      game: this.game,
      x: this.world.centerX,
      y: this.world.centerY,
      asset: 'mushroom'
    })

    this.player = new AnimePotato({
      game: this.game,
      x: this.world.centerX,
      y: this.world.centerY,
      asset: 'a-potato'
    })

    this.game.add.existing(this.mushroom)
    this.game.add.existing(this.player)

    this.game.physics.startSystem(Phaser.Physics.ARCADE)
    this.game.physics.enable([this.player, this.mushroom])

    this.player.animations.add('cycle')
    this.player.scale = {
      x: playerScale,
      y: playerScale
    }
    this.player.body.onCollide = new Phaser.Signal()
    this.player.body.onCollide.add((sprite1, sprite2) => {
    })

    this.cursors = this.game.input.keyboard.createCursorKeys()

  update () {
    const {player} = this
    const {body, scale} = player
    const {velocity} = body
    const {up, down, left, right} = this.cursors
    const {x, y} = velocity
    const slideFriction = 5
    let isWalking = false

    if (up.isDown) {
      velocity.y = -walkVelocity
      isWalking = true
    }
    if (down.isDown) {
      velocity.y = walkVelocity
      isWalking = true
    }
    if (left.isDown) {
      velocity.x = -walkVelocity
      isWalking = true
      scale.x = -1
    }
    if (right.isDown) {
      velocity.x = walkVelocity
      isWalking = true
      scale.x = 1
    }
    if (down.isUp && up.isUp) {
      if (y > 0) {
        velocity.y -= slideFriction
        if (y < 0) velocity.y = 0
      }
      if (y < 0) {
        velocity.y += slideFriction
        if (y > 0) velocity.y = 0
      }
    }
    if (left.isUp && right.isUp) {
      if (x > 0) {
        velocity.x -= slideFriction
        if (x < 0) velocity.x = 0
      }
      if (x < 0) {
        velocity.x += slideFriction
        if (x > 0) velocity.x = 0
      }
    }
    if (isWalking) {
      this.player.animations.play('cycle', 8)
    } else {
      this.player.frame = 0
      this.player.animations.stop()
    }

    this.game.physics.arcade.collide(this.player, this.mushroom, (sprite1, sprite2) => {
    })
  }

  render () {
    if (__DEV__) {
      this.game.debug.bodyInfo(this.player, 16, 24)
    }
  }
}
<|endoftext|>


<commit_before>/* globals __DEV__ */
import Phaser from 'phaser'
import SongFactory from '../service_objects/SongFactory'
import Hud from '../game_objects/Hud'
import Fatty from '../game_objects/Fatty'

export default class Game extends Phaser.State {
  init () {}
  preload () {
    this.load.image('mushroom', './assets/images/mushroom2.png');
    this.load.image('beach', './assets/images/background.png');
    this.load.image('fatty', './assets/images/bodilicious.png');
    this.load.image('left_cheek', './assets/images/nalga_l.png');
    this.load.image('right_cheek', './assets/images/nalga_r.png');
    this.load.image('loaderBar', './assets/images/loader-bar.png')

    this.load.image('gui_hud', './assets/images/gui_hud.png');
    this.load.image('gui_channel', './assets/images/gui_channel.png');

    this.load.image('arrow', './assets/images/flecha.png');
    this.load.image('cheeks', './assets/images/nalgas.png');

    this.load.image('people', './assets/images/people_a.png');
    this.load.image('mentor', './assets/images/instructor_a.png');
    this.load.image('sea', './assets/images/sea.gif');

    this.load.audio('clap', 'assets/sounds/clap.wav');
    this.load.audio('song', 'assets/sounds/song2.mp3');
  }

  create () {
    let  factory;
    let currentSong;
    let fatty;
    let people;
    let mentor;
    let sea;
    let gui_channel;

    this.claped = false;

    this.game.physics.startSystem(Phaser.Physics.ARCADE);
    this.game.physics.arcade.gravity.y = 600;
    this.game.add.sprite(0, 0, 'beach');

    this.clap = game.add.audio('clap');
    this.song = game.add.audio('song');
    this.song.play();
    // this.clap.allowMultiple = true;
    // this.clap.addMarker('clap', 0, 0.5);

    people = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY, 'people');
    people.anchor.setTo(0.5);

    mentor = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY - 200, 'mentor');
    mentor.anchor.setTo(0.5);

    sea = this.game.add.sprite(0, this.game.world.height - 700, 'sea');
    //mentor.anchor.setTo(0.5);

    gui_channel = this.game.add.sprite(0, 90, 'gui_channel');
    gui_channel.width = 350;
    gui_channel.height = this.game.world.height - 90;

    factory = new SongFactory(this.game);

    currentSong = factory.songs[0];
    factory._startSong(currentSong);

    this.noteSprites = factory._sprites(currentSong);
    this.score = 0;
    this.hud = new Hud({game:this.game});
    this.game.add.group(this.hud);
    this.ldr = this.game.add.sprite(this.game.world.centerX,this.game.world.height - 70, 'loaderBar');
    this.fatty = new Fatty({game:this.game});
    this.game.add.group(this.fatty);

    this.lc = this.game.add.sprite(this.game.world.centerX-80, this.game.world.centerY-60, 'left_cheek');
    this.rc = this.game.add.sprite(this.game.world.centerX+160, this.game.world.centerY-60, 'right_cheek');
    this.game.physics.arcade.enable([this.lc,this.ldr,this.rc]);
    this.ldr.body.allowGravity = false;
    this.lc.body.bounce.y = 0.7;
    this.rc.body.bounce.y = 0.7;
    this.ldr.body.immovable = true;
    // this.ldr.alpha = 0;
    this.lc.body.collideWorldBounds = true;
    this.rc.body.collideWorldBounds = true;
    console.log(this.ldr);

    this.lastIndex = 0;
    this.songStatus = {
      index: 0,
      range: null,
      note: null,
      status: null
    }
    this._createTitle('Killer Twerking');

    this.cursors = this.game.input.keyboard.createCursorKeys();
    //console.log(this.fatty.leftCheek);
  }

  _checkInput(key, symbol) {
    if (key.isDown) {
      if(this.songStatus.note && this.songStatus.note.symbol == symbol && this.songStatus.status != 'done') {
        //console.log("!!!!!!!")

        // if(this.songStatus.range == 'perfect') {
        //   this.clap.play();
        // }
        this.banner.text = this.songStatus.range;
        this.songStatus.status = 'done';
        this._updateScore(this.songStatus.range);
        switch(symbol){
          case 'l':
            console.log('Switch')
            this.lc.y -= 15;
            //this._moveLeftCheek
            break;
          case 'r':
            this.rc.y -= 15;
            break;
          case 'n':
            this.lc.y -= 15;
            this.rc.y -= 15;
            break;
          default:
        }
        //console.log(this.songStatus.range);
        //console.log("!!!!!!!")
      }
    }
  }

  update() {
    this.game.physics.arcade.collide([this.lc,this.rc], this.ldr)
    let sprite = this.noteSprites[0];
    if(sprite) {
      let hudSprite;
      hudSprite = this.hud._spriteByNote(sprite.data);
      this._check(sprite, hudSprite);
    } else {
      this.song.fadeIn(2000);
      this.banner.text = 'FIN DE CANCIÓN';
      this.state.start('Finish');
    }

    this._checkInput(this.cursors.left, 'l');
    this._checkInput(this.cursors.right, 'r');
    this._checkInput(this.cursors.down, 'n');
  }

  _createTitle(text) {
    this.banner;
    this.banner = this.add.text(this.world.centerX, this.world.centerY, text)
    this.banner.font = 'Bangers'
    this.banner.padding.set(10, 16)
    this.banner.fontSize = 40
    this.banner.fill = '#77BFA3'
    this.banner.smoothed = false
    this.banner.anchor.setTo(0.5)
  }

  _checkRange(sprite, hubSprite, range, name, callback) {
    let boundsSprite = sprite.getBounds();
    let boundsHubSprite= hubSprite.getBounds();

    let centerHub = {
      x: (boundsHubSprite.x + boundsHubSprite.width) / 2,
      y: (boundsHubSprite.height - boundsHubSprite.y) / 2
    }

    let centerSprite = {
      x: (boundsSprite.x + boundsSprite.width) / 2,
      y: (boundsSprite.height - boundsSprite.y) / 2
    }

    if(centerHub.y - range < centerSprite.y) {
      if(this.songStatus.range == 'perfect' && !this.claped) {
        //this.clap.play();
        this.claped = true;
      }
      this.songStatus.range = name;
      this.songStatus.note = sprite.data;
      if (callback) callback();
    }
  }
  _moveLeftCheek(){
    this.fatty.set(this.fatty.leftCheek,'y',5,false,false,1);
    console.log('Hola')
    //setTimeout(this.fatty.set(this.fatty.leftCheek,'y',5,false,false,2), 500);
  }
  _updateScore(name){
    switch(name){
      case 'bad':
        this.score += 1;
        break;
      case 'good':
        this.score += 2;
        break;
      case 'perfect':
        this.score += 3;
        break;
      default:
        console.log(this.score);
    }
    console.log(this.score);
    console.log(name);
  }

  _check(sprite, hubSprite) {
    this._checkRange(sprite, hubSprite, 10, 'bad');
    this._checkRange(sprite, hubSprite, 8, 'good');
    this._checkRange(sprite, hubSprite, 4, 'perfect');
    this._checkRange(sprite, hubSprite, -8, 'good');
    this._checkRange(sprite, hubSprite, -10, 'bad');
    this._checkRange(sprite, hubSprite, -12, 'missed', () => {
      if(this.songStatus.status != 'done') {
        this.banner.text = 'missed';
      }
      this.songStatus = {
        index: 0,
        range: null,
        note: null,
        status: null
      }
      this.noteSprites.splice(0,1);
      this.claped = false;
    });
  }

  menuOnClick(){
    this.state.start('Menu')
  }
  render () {

  }
}
<commit_msg>Fadings<commit_after>/* globals __DEV__ */
import Phaser from 'phaser'
import SongFactory from '../service_objects/SongFactory'
import Hud from '../game_objects/Hud'
import Fatty from '../game_objects/Fatty'

export default class Game extends Phaser.State {
  init () {}
  preload () {
    this.load.image('mushroom', './assets/images/mushroom2.png');
    this.load.image('beach', './assets/images/background.png');
    this.load.image('fatty', './assets/images/bodilicious.png');
    this.load.image('left_cheek', './assets/images/nalga_l.png');
    this.load.image('right_cheek', './assets/images/nalga_r.png');
    this.load.image('loaderBar', './assets/images/loader-bar.png')

    this.load.image('gui_hud', './assets/images/gui_hud.png');
    this.load.image('gui_channel', './assets/images/gui_channel.png');

    this.load.image('arrow', './assets/images/flecha.png');
    this.load.image('cheeks', './assets/images/nalgas.png');

    this.load.image('people', './assets/images/people_a.png');
    this.load.image('mentor', './assets/images/instructor_a.png');
    this.load.image('sea', './assets/images/sea.gif');

    this.load.audio('clap', 'assets/sounds/clap.wav');
    this.load.audio('song', 'assets/sounds/song.mp3');
  }

  create () {
    let  factory;
    let currentSong;
    let fatty;
    let people;
    let mentor;
    let sea;
    let gui_channel;

    this.claped = false;

    this.game.physics.startSystem(Phaser.Physics.ARCADE);
    this.game.physics.arcade.gravity.y = 600;
    this.game.add.sprite(0, 0, 'beach');

    this.clap = game.add.audio('clap');
    this.song = game.add.audio('song');
    this.song.onDecoded.add(() => {
      this.song.fadeIn(3000)
    }, this);

    //this.song.play();
    // this.clap.allowMultiple = true;
    // this.clap.addMarker('clap', 0, 0.5);

    people = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY, 'people');
    people.anchor.setTo(0.5);

    mentor = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY - 200, 'mentor');
    mentor.anchor.setTo(0.5);

    sea = this.game.add.sprite(0, this.game.world.height - 700, 'sea');
    //mentor.anchor.setTo(0.5);

    gui_channel = this.game.add.sprite(0, 90, 'gui_channel');
    gui_channel.width = 350;
    gui_channel.height = this.game.world.height - 90;

    factory = new SongFactory(this.game);

    currentSong = factory.songs[0];
    factory._startSong(currentSong);

    this.noteSprites = factory._sprites(currentSong);
    this.score = 0;
    this.hud = new Hud({game:this.game});
    this.game.add.group(this.hud);
    this.ldr = this.game.add.sprite(this.game.world.centerX,this.game.world.height - 70, 'loaderBar');
    this.fatty = new Fatty({game:this.game});
    this.game.add.group(this.fatty);

    this.lc = this.game.add.sprite(this.game.world.centerX-80, this.game.world.centerY-60, 'left_cheek');
    this.rc = this.game.add.sprite(this.game.world.centerX+160, this.game.world.centerY-60, 'right_cheek');
    this.game.physics.arcade.enable([this.lc,this.ldr,this.rc]);
    this.ldr.body.allowGravity = false;
    this.lc.body.bounce.y = 0.7;
    this.rc.body.bounce.y = 0.7;
    this.ldr.body.immovable = true;
    // this.ldr.alpha = 0;
    this.lc.body.collideWorldBounds = true;
    this.rc.body.collideWorldBounds = true;
    console.log(this.ldr);

    this.lastIndex = 0;
    this.songStatus = {
      index: 0,
      range: null,
      note: null,
      status: null
    }
    this._createTitle('');
    this._createScore(0);

    this.cursors = this.game.input.keyboard.createCursorKeys();
    //console.log(this.fatty.leftCheek);
  }

  _checkInput(key, symbol) {
    if (key.isDown) {
      if(this.songStatus.note && this.songStatus.note.symbol == symbol && this.songStatus.status != 'done') {
        //console.log("!!!!!!!")

        // if(this.songStatus.range == 'perfect') {
        //   this.clap.play();
        // }
        this.banner.text = this.songStatus.range;
        this.songStatus.status = 'done';
        this._updateScore(this.songStatus.range);
        switch(symbol){
          case 'l':
            console.log('Switch')
            this.lc.y -= 15;
            //this._moveLeftCheek
            break;
          case 'r':
            this.rc.y -= 15;
            break;
          case 'n':
            this.lc.y -= 15;
            this.rc.y -= 15;
            break;
          default:
        }
        //console.log(this.songStatus.range);
        //console.log("!!!!!!!")
      }
    }
  }

  update() {
    this.game.physics.arcade.collide([this.lc,this.rc], this.ldr)
    let sprite = this.noteSprites[0];

    if(sprite) {
      let hudSprite;
      hudSprite = this.hud._spriteByNote(sprite.data);
      this._check(sprite, hudSprite);
    } else {
      console.log('VOLUMEN!',this.song.volume);
      this.song.volume = this.song.volume * 0.95;
      game.time.events.add(1300, () =>{
        this.song.stop();
        this.state.start('Finish');
      });
    }

    this._checkInput(this.cursors.left, 'l');
    this._checkInput(this.cursors.right, 'r');
    this._checkInput(this.cursors.down, 'n');
  }

  _createScore(score) {
    this.scoreText;
    this.scoreText = this.add.text(this.world.width - 100, 50, `Score: ${score}`)
    this.scoreText.font = 'Bangers'
    this.scoreText.padding.set(10, 16)
    this.scoreText.fontSize = 30
    this.scoreText.fill = '#DDD'
    this.scoreText.strokeThickness = 1
    this.scoreText.smoothed = false
    this.scoreText.anchor.setTo(0.5)
  }

  _createTitle(text) {
    this.banner;
    this.banner = this.add.text(180, this.world.centerY - 50, text)
    this.banner.font = 'Bangers'
    this.banner.padding.set(10, 16)
    this.banner.fontSize = 70
    this.banner.fill = '#E37F26'
    this.banner.strokeThickness = 3
    this.banner.smoothed = false
    this.banner.anchor.setTo(0.5)
  }

  _checkRange(sprite, hubSprite, range, name, callback) {
    let boundsSprite = sprite.getBounds();
    let boundsHubSprite= hubSprite.getBounds();

    let centerHub = {
      x: (boundsHubSprite.x + boundsHubSprite.width) / 2,
      y: (boundsHubSprite.height - boundsHubSprite.y) / 2
    }

    let centerSprite = {
      x: (boundsSprite.x + boundsSprite.width) / 2,
      y: (boundsSprite.height - boundsSprite.y) / 2
    }

    if(centerHub.y - range < centerSprite.y) {
      if(this.songStatus.range == 'perfect' && !this.claped) {
        this.clap.play();
        this.claped = true;
      }
      this.songStatus.range = name;
      this.songStatus.note = sprite.data;
      if (callback) callback();
    }
  }
  _moveLeftCheek(){
    this.fatty.set(this.fatty.leftCheek,'y',5,false,false,1);
    console.log('Hola')
    //setTimeout(this.fatty.set(this.fatty.leftCheek,'y',5,false,false,2), 500);
  }
  _updateScore(name){
    switch(name){
      case 'bad':
        this.score += 1;
        break;
      case 'good':
        this.score += 2;
        break;
      case 'perfect':
        this.score += 3;
        break;
      default:
        console.log(this.score);
    }
    this.scoreText.text = `Score: ${this.score}`;
    console.log(this.score);
    console.log(name);
  }

  _check(sprite, hubSprite) {
    this._checkRange(sprite, hubSprite, 10, 'bad');
    this._checkRange(sprite, hubSprite, 8, 'good');
    this._checkRange(sprite, hubSprite, 4, 'perfect');
    this._checkRange(sprite, hubSprite, -8, 'good');
    this._checkRange(sprite, hubSprite, -10, 'bad');
    this._checkRange(sprite, hubSprite, -12, 'missed', () => {
      if(this.songStatus.status != 'done') {
        this.banner.text = 'missed';
      }
      this.songStatus = {
        index: 0,
        range: null,
        note: null,
        status: null
      }
      this.noteSprites.splice(0,1);
      this.claped = false;
    });
  }

  menuOnClick(){
    this.state.start('Menu')
  }
  render () {

  }
}
<|endoftext|>


<commit_before>import Phaser from 'phaser'
import config from '../config'
import {makeGreen, makeYellow, getRandomCheer, isTouchDevice} from '../utils'
import Player from '../sprites/Player'
import Input from '../Input'
import _ from 'lodash'

export default class extends Phaser.State {
	init() {
		this.game.sound.mute = this.loadSoundMuteState()
		this.skipIntro = this.loadSkipIntro()
		this.jumping = false
	}

	preload() {
		// load sounds
		this.soundCoin = this.game.add.audio('coin')
		this.soundOuch = this.game.add.audio('ouch')
	}

	create() {
		// create map
		this.map = this.game.add.tilemap('liip')
		this.map.addTilesetImage('tiles_spritesheet', 'gameTiles')

		// create layers
		this.backgroundLayer = this.map.createLayer('backgroundLayer')
		this.blockedLayer = this.map.createLayer('blockedLayer')
		// this.game.world.width may cause problems with collisions, keep in mind
		this.map.setCollisionBetween(1, this.game.world.width, true, 'blockedLayer', true)
		this.backgroundLayer.resizeWorld()

		// add objects
		this.addObjectsLayer()

		// add timeline layer
		this.addTimelineObjectsLayer()

		// add timeline layer
		this.addYearLabelLayer()

		if ( ! this.skipIntro ) {
			// add intro layer
			this.addIntroLayer()
		}

		// this group holds all sprites/labels that should be fixed to camera
		this.infoLabels = this.game.add.group()
		this.infoLabels.fixedToCamera = true

		let logo = this.game.add.sprite(config.infoLabelsPadding, config.infoLabelsPadding, 'liipLogoSmall')
		logo.anchor.set(0, 0.5)
		logo.scale.setTo(0.5)
		this.infoLabels.add(logo)

		// setup player
		let playerStartPositionX = 0
		if ( this.skipIntro ) {
			playerStartPositionX = 3000
		}
		this.player = new Player({
			game: this.game,
			x: playerStartPositionX,
			y: 250,
			asset: 'player'
		})
		this.player.enable()

		// score / highscore
		let scoreOffset = 0
		// if user had a previous highscore, show it
		let highscore = this.loadScore()
		if (highscore) {
			this.highscoreLabel = this.game.add.text(this.game.width - config.infoLabelsPadding, config.infoLabelsPadding, ' / ' + highscore, config.text.score)
			this.highscoreLabel.anchor.set(1, 0.5)
			this.infoLabels.add(this.highscoreLabel)
			scoreOffset = this.highscoreLabel.width
		}
		this.scoreLabel = this.game.add.text(this.game.width - (config.infoLabelsPadding + scoreOffset), config.infoLabelsPadding, '0', makeGreen(config.text.score))
		this.scoreLabel.anchor.set(1, 0.5)
		this.infoLabels.add(this.scoreLabel)

		// current position
		this.positionLabel = this.game.add.text(this.game.width / 2, config.infoLabelsPadding, '2007', Object.assign(config.text.xl, {boundsAlignH: 'center', boundsAlignV: 'top'}))
		this.positionLabel.anchor.set(0.5, 0.5)
		this.infoLabels.add(this.positionLabel)

		// mute button
		this.muteBtn = this.game.add.text(config.infoLabelsPadding, this.game.height - config.infoLabelsPadding, (this.game.sound.mute ? 'unmute' : 'mute'), Object.assign(config.text.md, { boundsAlignH: 'left', boundsAlignV: 'bottom'}))
		this.muteBtn.anchor.set(0, 0.5)
		this.muteBtn.inputEnabled = true
		this.muteBtn.events.onInputDown.add(() => {
			this.game.sound.mute = !this.game.sound.mute
			this.saveSoundMuteState(this.game.sound.mute)
			this.muteBtn.text = (this.game.sound.mute ? 'unmute' : 'mute')
		})
		this.infoLabels.add(this.muteBtn)

		if ( ! this.skipIntro ) {
			// add intro text
			this.firstJumpDone = false
			let howToJump = isTouchDevice() ? 'Tap your screen' : 'Press space'
			this.introLabel = this.game.add.text(this.game.width / 2, 200, howToJump + ' to jump', Object.assign(config.text.xl, {boundsAlignH: 'center', boundsAlignV: 'center'}))
			this.introLabel.anchor.set(0.5, 0.5)
			this.infoLabels.add(this.introLabel)
		}

		// init input (keyboard or tap on mobile)
		this.input = new Input({ game: this.game, muteBtn: this.muteBtn })
	}

	update() {
		this.game.physics.arcade.collide(this.player, this.blockedLayer, this.playerHit, null, this)

		// set camera focus with some x offset
		this.camera.focusOnXY(this.player.x + (this.game.width / 4), this.player.y)

		if (this.player.alive) {
			// if player is back on ground reset to walk animation
			if(this.jumping && this.player.body.blocked.down) {
				this.player.loadTexture('player')
				this.player.animations.stop('jump', true)
				this.player.animations.play('walk', 18, true)
				this.jumping = false
			}

			if (this.input.shouldJump()) {
				this.jumping = this.player.jump()
				if ( ! this.skipIntro && ! this.firstJumpDone ) {
					this.firstJumpDone = true
					this.introLabel.text = ''
				}
			}

			this.addToScore(1)
		}

		// make objects collectable
		this.game.physics.arcade.overlap(this.player, this.objectsLayer, this.collect, null, this)

		// make timeline objects collectable
		this.game.physics.arcade.overlap(this.player, this.timelineObjectsLayer, this.collectTimelineObject, null, this)

		// enable year barriers
		this.game.physics.arcade.overlap(this.player, this.yearBarrierLayer, this.passYearBarrier, null, this)

		if ( ! this.skipIntro ) {
			// enable intro barriers
			this.game.physics.arcade.overlap(this.player, this.introBarrierLayer, this.passIntroBarrier, null, this)
		}

		// restart the game if reaching the edge
		if (this.player.x >= this.game.world.width) {
			this.game.time.events.add(1500, this.gameOver, this)
		}
	}

	gameOver() {
		// cleanup game state - remove all items
		_(this.timelineObjectsLayer.children)
			.concat(this.objectsLayer.children)
			.concat(this.infoLabels.children)
			.filter()
			.each((item) => {
				item.destroy()
			})
		// leave player
		this.player.body.moves = false
		this.game.state.start('GameOver', false, false)
	}

	restart() {
		this.game.state.start('Game')
	}

	playerHit(player, blockedLayer) {
		if (player.body.blocked.right && this.player.alive) {
			this.soundOuch.play()
			// kill player
			this.player.die()
			// go to gameover after a few milliseconds
			this.game.time.events.add(1500, this.gameOver, this)
			this.saveScore()
		}
	}

	addToScore(newScore) {
		// this.score = newScore
		let score = parseInt(this.scoreLabel.text, 10) + newScore
		this.scoreLabel.text = score
	}

	addObjectsLayer() {
		this.objectsLayer = this.game.add.group()
		this.objectsLayer.enableBody = true
		let objects = this.map.objects['objectsLayer']

		objects.forEach((object) => {
			let sprite = this.objectsLayer.create(object.x, object.y - config.tileSize, object.properties.sprite)
			// copy all properties to the sprite
			Object.keys(object.properties).forEach(key => {
				sprite[key] = object.properties[key]
			})
		})
	}

	addTimelineObjectsLayer() {
		this.timelineObjectsLayer = this.game.add.group()
		this.timelineObjectsLayer.enableBody = true
		let timelineObjects = this.map.objects['timelineLayer']

		timelineObjects.forEach((timelineObject) => {
			let positionX = timelineObject.x
			let positionY = timelineObject.y - config.tileSize
			let text = timelineObject.properties.text
			let sprite = this.timelineObjectsLayer.create(positionX, positionY, timelineObject.properties.sprite)
			let labelPositionX = Math.floor(sprite.width / 2)
			let labelPositionY = config.tileSize + 20
			let label = this.game.add.text(labelPositionX, labelPositionY, text, makeGreen(Object.assign(config.text.md, {align: 'center'})))
			label.anchor.set(0.5)
			// copy all properties to the sprite
			Object.keys(timelineObject.properties).forEach(key => {
				sprite[key] = timelineObject.properties[key]
			})
			sprite.addChild(label)
		})
	}

	addYearLabelLayer() {
		this.yearLabelLayer = this.game.add.group()
		this.yearBarrierLayer = this.game.add.group()
		this.yearBarrierLayer.enableBody = true
		let yearObjects = this.map.objects['yearLayer']

		yearObjects.forEach((yearObject) => {
			let text = yearObject.properties.year
			let labelPositionX = yearObject.x
			let labelPositionY = yearObject.y
			let label = this.game.add.text(labelPositionX, labelPositionY, text, Object.assign(config.text.md, {align: 'center'}), this.yearLabelLayer)
			label.anchor.set(0.5)
			if(text !== '2007') {
				let yearBarrier = this.yearBarrierLayer.create(yearObject.x, 0)
				yearBarrier.scale.x = 1
				yearBarrier.scale.y = this.game.world.height
				yearBarrier.yearLabel = text
			}
		})
	}

	addIntroLayer() {
		this.introBarrierLayer = this.game.add.group()
		this.introBarrierLayer.enableBody = true
		let introObjects = this.map.objects['introLayer']

		introObjects.forEach((introObject) => {
			let type = introObject.properties.intro
			let introBarrier = this.introBarrierLayer.create(introObject.x, 0)
			introBarrier.scale.x = 1
			introBarrier.scale.y = this.game.world.height
			introBarrier.intro_type = type
		})
	}

	collect(player, collectable) {
		// speed up player
		this.player.speedUp()

		this.showNotice(collectable.x, collectable.y, '+' + config.points.coin, makeYellow(config.text.xl))

		// play audio
		this.soundCoin.play()
		// update score
		this.addToScore(config.points.coin)
		// remove sprite
		collectable.destroy()
	}

	collectTimelineObject(player, collectable) {
		let points = 0
		if(collectable.type === 'award') {
			points = config.points.award
		}

		this.showNotice(collectable.x, collectable.y, getRandomCheer(), makeGreen(config.text.xl))

		// play audio
		this.soundCoin.play()
		// update score
		this.addToScore(points)
		// remove sprite
		collectable.destroy()
	}

	showNotice(x, y, text, style) {
		// show notice
		let notice = this.game.add.text(x, y, text, style)

		// animate notice
		let noticeTween = this.game.add.tween(notice).to({alpha: 0, y: notice.y - 30}, 800, Phaser.Easing.Linear.None, true)
		noticeTween.onComplete.addOnce((notice) => {
			notice.destroy()
		})
	}

	passYearBarrier(player, collectable) {
		// update year label
		this.positionLabel.text = collectable.yearLabel

		// animate new year label
		let yearTween = this.game.add.tween(this.positionLabel).to({alpha: 0, fontSize: 86}, 500, Phaser.Easing.Linear.None, true)
		yearTween.onComplete.addOnce((positionLabel) => {
			positionLabel.fontSize = 26
			positionLabel.alpha = 1
		})
		collectable.destroy()
	}

	passIntroBarrier(player, collectable) {
		console.log(collectable);
		if ( collectable.intro_type === 'jump' ) {
			this.introLabel.text = 'Get Extra Points (and get faster)'
			this.firstJumpDone = true
		}
		if ( collectable.intro_type === 'objects' ) {
			this.introLabel.text = 'Get Liip Achievements'
		}
		if ( collectable.intro_type === 'timeline' ) {
			this.introLabel.destroy()
			this.saveSkipIntro();
		}

		collectable.destroy()
	}

	/**
	 * Save score to local storage
	 */
	saveScore() {
		let previousScore = this.loadScore(),
			currentScore = parseInt(this.scoreLabel.text, 10)

		// only set score if we don't yet have one or if currentScore is greater than previous one
		if (!previousScore || currentScore > previousScore) {
			localStorage.setItem(config.localStorageName + '-highscore', currentScore)
		}
	}

	/**
	 * Load score from local storage
	 */
	loadScore() {
		return parseInt(localStorage.getItem(config.localStorageName + '-highscore'))
	}

	/**
	 * Save sound mute state to local storage
	 */
	saveSoundMuteState(mute) {
		localStorage.setItem(config.localStorageName + '-mute', mute)
	}

	/**
	 * Load sound mute state from local storage
	 */
	loadSoundMuteState() {
		return localStorage.getItem(config.localStorageName + '-mute') === 'true'
	}

	/**
	 * Save skip intro flag to local storage
	 */
	saveSkipIntro() {
		localStorage.setItem(config.localStorageName + '-skip-intro', true)
	}

	/**
	 * Load skip intro flag from local storage
	 */
	loadSkipIntro() {
		return localStorage.getItem(config.localStorageName + '-skip-intro') === 'true'
	}
}
<commit_msg>flip objects and achievements in intro<commit_after>import Phaser from 'phaser'
import config from '../config'
import {makeGreen, makeYellow, getRandomCheer, isTouchDevice} from '../utils'
import Player from '../sprites/Player'
import Input from '../Input'
import _ from 'lodash'

export default class extends Phaser.State {
	init() {
		this.game.sound.mute = this.loadSoundMuteState()
		this.skipIntro = this.loadSkipIntro()
		this.jumping = false
	}

	preload() {
		// load sounds
		this.soundCoin = this.game.add.audio('coin')
		this.soundOuch = this.game.add.audio('ouch')
	}

	create() {
		// create map
		this.map = this.game.add.tilemap('liip')
		this.map.addTilesetImage('tiles_spritesheet', 'gameTiles')

		// create layers
		this.backgroundLayer = this.map.createLayer('backgroundLayer')
		this.blockedLayer = this.map.createLayer('blockedLayer')
		// this.game.world.width may cause problems with collisions, keep in mind
		this.map.setCollisionBetween(1, this.game.world.width, true, 'blockedLayer', true)
		this.backgroundLayer.resizeWorld()

		// add objects
		this.addObjectsLayer()

		// add timeline layer
		this.addTimelineObjectsLayer()

		// add timeline layer
		this.addYearLabelLayer()

		if ( ! this.skipIntro ) {
			// add intro layer
			this.addIntroLayer()
		}

		// this group holds all sprites/labels that should be fixed to camera
		this.infoLabels = this.game.add.group()
		this.infoLabels.fixedToCamera = true

		let logo = this.game.add.sprite(config.infoLabelsPadding, config.infoLabelsPadding, 'liipLogoSmall')
		logo.anchor.set(0, 0.5)
		logo.scale.setTo(0.5)
		this.infoLabels.add(logo)

		// setup player
		let playerStartPositionX = 0
		if ( this.skipIntro ) {
			playerStartPositionX = 3000
		}
		this.player = new Player({
			game: this.game,
			x: playerStartPositionX,
			y: 250,
			asset: 'player'
		})
		this.player.enable()

		// score / highscore
		let scoreOffset = 0
		// if user had a previous highscore, show it
		let highscore = this.loadScore()
		if (highscore) {
			this.highscoreLabel = this.game.add.text(this.game.width - config.infoLabelsPadding, config.infoLabelsPadding, ' / ' + highscore, config.text.score)
			this.highscoreLabel.anchor.set(1, 0.5)
			this.infoLabels.add(this.highscoreLabel)
			scoreOffset = this.highscoreLabel.width
		}
		this.scoreLabel = this.game.add.text(this.game.width - (config.infoLabelsPadding + scoreOffset), config.infoLabelsPadding, '0', makeGreen(config.text.score))
		this.scoreLabel.anchor.set(1, 0.5)
		this.infoLabels.add(this.scoreLabel)

		// current position
		this.positionLabel = this.game.add.text(this.game.width / 2, config.infoLabelsPadding, '2007', Object.assign(config.text.xl, {boundsAlignH: 'center', boundsAlignV: 'top'}))
		this.positionLabel.anchor.set(0.5, 0.5)
		this.infoLabels.add(this.positionLabel)

		// mute button
		this.muteBtn = this.game.add.text(config.infoLabelsPadding, this.game.height - config.infoLabelsPadding, (this.game.sound.mute ? 'unmute' : 'mute'), Object.assign(config.text.md, { boundsAlignH: 'left', boundsAlignV: 'bottom'}))
		this.muteBtn.anchor.set(0, 0.5)
		this.muteBtn.inputEnabled = true
		this.muteBtn.events.onInputDown.add(() => {
			this.game.sound.mute = !this.game.sound.mute
			this.saveSoundMuteState(this.game.sound.mute)
			this.muteBtn.text = (this.game.sound.mute ? 'unmute' : 'mute')
		})
		this.infoLabels.add(this.muteBtn)

		if ( ! this.skipIntro ) {
			// add intro text
			this.firstJumpDone = false
			let howToJump = isTouchDevice() ? 'Tap your screen' : 'Press space'
			this.introLabel = this.game.add.text(this.game.width / 2, 200, howToJump + ' to jump', Object.assign(config.text.xl, {boundsAlignH: 'center', boundsAlignV: 'center'}))
			this.introLabel.anchor.set(0.5, 0.5)
			this.infoLabels.add(this.introLabel)
		}

		// init input (keyboard or tap on mobile)
		this.input = new Input({ game: this.game, muteBtn: this.muteBtn })
	}

	update() {
		this.game.physics.arcade.collide(this.player, this.blockedLayer, this.playerHit, null, this)

		// set camera focus with some x offset
		this.camera.focusOnXY(this.player.x + (this.game.width / 4), this.player.y)

		if (this.player.alive) {
			// if player is back on ground reset to walk animation
			if(this.jumping && this.player.body.blocked.down) {
				this.player.loadTexture('player')
				this.player.animations.stop('jump', true)
				this.player.animations.play('walk', 18, true)
				this.jumping = false
			}

			if (this.input.shouldJump()) {
				this.jumping = this.player.jump()
				if ( ! this.skipIntro && ! this.firstJumpDone ) {
					this.firstJumpDone = true
					this.introLabel.text = ''
				}
			}

			this.addToScore(1)
		}

		// make objects collectable
		this.game.physics.arcade.overlap(this.player, this.objectsLayer, this.collect, null, this)

		// make timeline objects collectable
		this.game.physics.arcade.overlap(this.player, this.timelineObjectsLayer, this.collectTimelineObject, null, this)

		// enable year barriers
		this.game.physics.arcade.overlap(this.player, this.yearBarrierLayer, this.passYearBarrier, null, this)

		if ( ! this.skipIntro ) {
			// enable intro barriers
			this.game.physics.arcade.overlap(this.player, this.introBarrierLayer, this.passIntroBarrier, null, this)
		}

		// restart the game if reaching the edge
		if (this.player.x >= this.game.world.width) {
			this.game.time.events.add(1500, this.gameOver, this)
		}
	}

	gameOver() {
		// cleanup game state - remove all items
		_(this.timelineObjectsLayer.children)
			.concat(this.objectsLayer.children)
			.concat(this.infoLabels.children)
			.filter()
			.each((item) => {
				item.destroy()
			})
		// leave player
		this.player.body.moves = false
		this.game.state.start('GameOver', false, false)
	}

	restart() {
		this.game.state.start('Game')
	}

	playerHit(player, blockedLayer) {
		if (player.body.blocked.right && this.player.alive) {
			this.soundOuch.play()
			// kill player
			this.player.die()
			// go to gameover after a few milliseconds
			this.game.time.events.add(1500, this.gameOver, this)
			this.saveScore()
		}
	}

	addToScore(newScore) {
		// this.score = newScore
		let score = parseInt(this.scoreLabel.text, 10) + newScore
		this.scoreLabel.text = score
	}

	addObjectsLayer() {
		this.objectsLayer = this.game.add.group()
		this.objectsLayer.enableBody = true
		let objects = this.map.objects['objectsLayer']

		objects.forEach((object) => {
			let sprite = this.objectsLayer.create(object.x, object.y - config.tileSize, object.properties.sprite)
			// copy all properties to the sprite
			Object.keys(object.properties).forEach(key => {
				sprite[key] = object.properties[key]
			})
		})
	}

	addTimelineObjectsLayer() {
		this.timelineObjectsLayer = this.game.add.group()
		this.timelineObjectsLayer.enableBody = true
		let timelineObjects = this.map.objects['timelineLayer']

		timelineObjects.forEach((timelineObject) => {
			let positionX = timelineObject.x
			let positionY = timelineObject.y - config.tileSize
			let text = timelineObject.properties.text
			let sprite = this.timelineObjectsLayer.create(positionX, positionY, timelineObject.properties.sprite)
			let labelPositionX = Math.floor(sprite.width / 2)
			let labelPositionY = config.tileSize + 20
			let label = this.game.add.text(labelPositionX, labelPositionY, text, makeGreen(Object.assign(config.text.md, {align: 'center'})))
			label.anchor.set(0.5)
			// copy all properties to the sprite
			Object.keys(timelineObject.properties).forEach(key => {
				sprite[key] = timelineObject.properties[key]
			})
			sprite.addChild(label)
		})
	}

	addYearLabelLayer() {
		this.yearLabelLayer = this.game.add.group()
		this.yearBarrierLayer = this.game.add.group()
		this.yearBarrierLayer.enableBody = true
		let yearObjects = this.map.objects['yearLayer']

		yearObjects.forEach((yearObject) => {
			let text = yearObject.properties.year
			let labelPositionX = yearObject.x
			let labelPositionY = yearObject.y
			let label = this.game.add.text(labelPositionX, labelPositionY, text, Object.assign(config.text.md, {align: 'center'}), this.yearLabelLayer)
			label.anchor.set(0.5)
			if(text !== '2007') {
				let yearBarrier = this.yearBarrierLayer.create(yearObject.x, 0)
				yearBarrier.scale.x = 1
				yearBarrier.scale.y = this.game.world.height
				yearBarrier.yearLabel = text
			}
		})
	}

	addIntroLayer() {
		this.introBarrierLayer = this.game.add.group()
		this.introBarrierLayer.enableBody = true
		let introObjects = this.map.objects['introLayer']

		introObjects.forEach((introObject) => {
			let type = introObject.properties.intro
			let introBarrier = this.introBarrierLayer.create(introObject.x, 0)
			introBarrier.scale.x = 1
			introBarrier.scale.y = this.game.world.height
			introBarrier.intro_type = type
		})
	}

	collect(player, collectable) {
		// speed up player
		this.player.speedUp()

		this.showNotice(collectable.x, collectable.y, '+' + config.points.coin, makeYellow(config.text.xl))

		// play audio
		this.soundCoin.play()
		// update score
		this.addToScore(config.points.coin)
		// remove sprite
		collectable.destroy()
	}

	collectTimelineObject(player, collectable) {
		let points = 0
		if(collectable.type === 'award') {
			points = config.points.award
		}

		this.showNotice(collectable.x, collectable.y, getRandomCheer(), makeGreen(config.text.xl))

		// play audio
		this.soundCoin.play()
		// update score
		this.addToScore(points)
		// remove sprite
		collectable.destroy()
	}

	showNotice(x, y, text, style) {
		// show notice
		let notice = this.game.add.text(x, y, text, style)

		// animate notice
		let noticeTween = this.game.add.tween(notice).to({alpha: 0, y: notice.y - 30}, 800, Phaser.Easing.Linear.None, true)
		noticeTween.onComplete.addOnce((notice) => {
			notice.destroy()
		})
	}

	passYearBarrier(player, collectable) {
		// update year label
		this.positionLabel.text = collectable.yearLabel

		// animate new year label
		let yearTween = this.game.add.tween(this.positionLabel).to({alpha: 0, fontSize: 86}, 500, Phaser.Easing.Linear.None, true)
		yearTween.onComplete.addOnce((positionLabel) => {
			positionLabel.fontSize = 26
			positionLabel.alpha = 1
		})
		collectable.destroy()
	}

	passIntroBarrier(player, collectable) {
		if ( collectable.intro_type === 'jump' ) {
			this.introLabel.text = 'Get Liip Achievements'
			this.firstJumpDone = true
		}
		if ( collectable.intro_type === 'timeline' ) {
			this.introLabel.text = 'Get Extra Points (and get faster)'
		}
		if ( collectable.intro_type === 'objects' ) {
			this.introLabel.destroy()
			this.saveSkipIntro()
		}

		collectable.destroy()
	}

	/**
	 * Save score to local storage
	 */
	saveScore() {
		let previousScore = this.loadScore(),
			currentScore = parseInt(this.scoreLabel.text, 10)

		// only set score if we don't yet have one or if currentScore is greater than previous one
		if (!previousScore || currentScore > previousScore) {
			localStorage.setItem(config.localStorageName + '-highscore', currentScore)
		}
	}

	/**
	 * Load score from local storage
	 */
	loadScore() {
		return parseInt(localStorage.getItem(config.localStorageName + '-highscore'))
	}

	/**
	 * Save sound mute state to local storage
	 */
	saveSoundMuteState(mute) {
		localStorage.setItem(config.localStorageName + '-mute', mute)
	}

	/**
	 * Load sound mute state from local storage
	 */
	loadSoundMuteState() {
		return localStorage.getItem(config.localStorageName + '-mute') === 'true'
	}

	/**
	 * Save skip intro flag to local storage
	 */
	saveSkipIntro() {
		localStorage.setItem(config.localStorageName + '-skip-intro', true)
	}

	/**
	 * Load skip intro flag from local storage
	 */
	loadSkipIntro() {
		return localStorage.getItem(config.localStorageName + '-skip-intro') === 'true'
	}
}
<|endoftext|>