<commit_before>

var helpers = require("./helpers")
var path    = require("path")
var fs      = require("fs")

// createRoute
//
//      302       /articles/:slug        /:slug
//
//       |              |                  |
//    status        inputPattern     outputPattern
//
var createRoute = exports.createRoute = function(status, inputPattern, outputPattern){
  var re = helpers.path2regexp(inputPattern)

  // route
  //
  //  A route is a function that takes a request path
  //  if the route is a match it returns instructions
  //  for a redirect. If no match, it returns null.
  //
  //  Eg. turns this...
  //
  //    /confessions/jesus-dont-want-me-for-a-sunbeam
  //
  //   into this...
  //
  //    { status: 302, path: "/" }
  //
  //   ...or returns null
  //
  return function route(requestPath){
    var params = helpers.matchURL(requestPath, re)

    if (params) {
      var pathOut = helpers.buildPath(outputPattern, params)

      // we dont want to redirect to the same path
      if (pathOut === requestPath) return null

      return ({
        pathIn  : requestPath,
        pathOut : pathOut,
        route   : [status, inputPattern, outputPattern]
      })
    }

    return null
  }

}

// var line2route = exports.line2route = function(line){
//   var arr   = line2arr(line)
//   var route = arr2route(arr)
//   return route
// }

//http://rubular.com/r/Bb52nWP82I
var re = new RegExp(/(\d{3})\s+(\/\S*)\s+(\S+)/)
var line2arr = exports.line2arr = function(line){
  var r = re.exec(line)
  if (r) {
    return [r[1], r[2], r[3]]
  } else {
    return null
  }
}

var arr2route = exports.arr2route = function(arr){
  if (arr){
    return createRoute.apply(this, arr)
  } else {
    return function(){ return null }
  }
}

var buff2arrs = exports.buff2arrs = function(buff){
  var arrs = buff.toString().split(/\r?\n/).clean("").map(line2arr)
  return arrs
}

exports.middleware = function(routerPath){

  if (typeof routerPath == 'function') {
    var fetchRoutes = routerPath
  } else {
    // returns array of routes.
    var fetchRoutes = function(req, rsp, cb){
      fs.readFile(path.resolve(routerPath), function(err, buff){
        if (buff) {
          var arrs = buff2arrs(buff)
          return cb(arrs)
        } else {
          return cb(null)
        }
      })
    }
  }

  return function(req, rsp, next){
    fetchRoutes(req, rsp, function(arrs){
      if (arrs === null) return next()

      for (var i = 0; i < arrs.length; i++){
        var redirect = arr2route(arrs[i])(req.url)
        if (redirect !== null) {
          rsp.statusCode = redirect.route[0]
          rsp.setHeader('Location', redirect.pathOut)
          rsp.end("redirecting to " + redirect.pathOut)
          return
        }
      }

      // arrs.forEach(function(arr){

      //   if (redirect !== null) {
      //     rsp.statusCode = redirect.route[0]
      //     rsp.setHeader('Location', redirect.pathOut)
      //     rsp.end("redirecting to " + redirect.pathOut)
      //     return
      //   }
      // })
      return next()
    })
  }

}
<commit_msg>tests for file parsing<commit_after>

var helpers = require("./helpers")
var path    = require("path")
var fs      = require("fs")

// createRoute
//
//      302       /articles/:slug        /:slug
//
//       |              |                  |
//    status        inputPattern     outputPattern
//
var createRoute = exports.createRoute = function(status, inputPattern, outputPattern){
  var re = helpers.path2regexp(inputPattern)

  // route
  //
  //  A route is a function that takes a request path
  //  if the route is a match it returns instructions
  //  for a redirect. If no match, it returns null.
  //
  //  Eg. turns this...
  //
  //    /confessions/jesus-dont-want-me-for-a-sunbeam
  //
  //   into this...
  //
  //    { status: 302, path: "/" }
  //
  //   ...or returns null
  //
  return function route(requestPath){
    var params = helpers.matchURL(requestPath, re)

    if (params) {
      var pathOut = helpers.buildPath(outputPattern, params)

      // we dont want to redirect to the same path
      if (pathOut === requestPath) return null

      return ({
        pathIn  : requestPath,
        pathOut : pathOut,
        route   : [status, inputPattern, outputPattern]
      })
    }

    return null
  }

}

// var line2route = exports.line2route = function(line){
//   var arr   = line2arr(line)
//   var route = arr2route(arr)
//   return route
// }

//http://rubular.com/r/Bb52nWP82I
var re = new RegExp(/(\d{3})\s+(\/\S*)\s+(\S+)/)
var line2arr = exports.line2arr = function(line){
  var r = re.exec(line)
  if (r) {
    return [r[1], r[2], r[3]]
  } else {
    return null
  }
}

var arr2route = exports.arr2route = function(arr){
  if (arr){
    return createRoute.apply(this, arr)
  } else {
    return function(){ return null }
  }
}

var buff2arrs = exports.buff2arrs = function(buff){
  var arrs = buff.toString().split(/\r?\n/).clean("").map(line2arr)
  return arrs
}

exports.middleware = function(routerPath){

  if (typeof routerPath == 'function') {
    var fetchRoutes = routerPath
  } else {
    // returns array of routes.
    var fetchRoutes = function(req, rsp, cb){
      fs.readFile(path.resolve(routerPath), function(err, buff){
        if (buff) {
          var arrs = buff2arrs(buff)
          return cb(arrs)
        } else {
          return cb(null)
        }
      })
    }
  }

  return function(req, rsp, next){
    fetchRoutes(req, rsp, function(arrs){
      if (arrs === null) return next()

      for (var i = 0; i < arrs.length; i++){
        var redirect = arr2route(arrs[i])(req.url)
        if (redirect !== null) {
          rsp.statusCode = redirect.route[0]
          rsp.setHeader('Location', redirect.pathOut)
          rsp.end("redirecting to " + redirect.pathOut)
          return
        }
      }

      // arrs.forEach(function(arr){

      //   if (redirect !== null) {
      //     rsp.statusCode = redirect.route[0]
      //     rsp.setHeader('Location', redirect.pathOut)
      //     rsp.end("redirecting to " + redirect.pathOut)
      //     return
      //   }
      // })
      return next()
    })
  }

}
<|endoftext|>


<commit_before>/**
 * XadillaX created at 2014-09-09 14:21
 *
 * Copyright (c) 2014 Huaban.com, all rights
 * reserved.
 */
"use strict";

var 囍 = require("lodash");
var util = require("util");
var mysql = require("mysql2");
var async = require("async");
var fieldType = require("./fieldType");
var ResultPromisor = require("./resultpromisor");

/**
 * Yakumo Yukari is the entity of Yakumo Toshihiko.
 * @param model
 * @param source
 * @constructor
 */
var Yukari = function(model, source) {
    this.$model = model;
    this.$toshihiko = model.toshihiko;

    this.$fields = model._fieldsObject;
    this.$origData = {};

    this.$source = source;

    this.$dbName = this.$toshihiko.database;
    this.$tableName = this.$model.name;
    this.$cache = model.cache;

    this.$fromCache = false;
};

/**
 * get primary keys and values
 * @param {Boolean} [fromOrig] is primary keys from original data
 * @returns {*}
 * @private
 */
Yukari.prototype._getPrimaryKeys = function(fromOrig) {
    var keys = this.$model.getPrimaryKeysName();
    if(typeof keys === "string") {
        return (fromOrig || this[keys] === undefined) ?
            this.$origData[keys] :
            this[keys];
    }

    var obj = {};
    for(var i = 0; i < keys.length; i++) {
        obj[keys[i]] = (fromOrig || this[keys[i]] === undefined) ?
            this.$origData[keys[i]] :
            this[keys[i]];
    }
    return obj;
};

/**
 * build row
 * @param row
 * @param useOrigName
 * @private
 */
Yukari.prototype._buildRow = function(row, useOrigName) {
    this.$origData = {};

    for(var i = 0; i < this.$fields.length; i++) {
        var field = this.$fields[i];
        var value = row[useOrigName ? field.column : field.name];

        if(undefined === value) {
            if(undefined !== field.defaultValue) {
                value = field.defaultValue;
            }
        }

        if(undefined === value) {
            continue;
        }

        this[field.name] = 囍.clone(value);
    }

    if(row.$fromCache) {
        this.$fromCache = true;
    }
};

/**
 * initialize row
 * @param row
 * @param useOrigName
 * @private
 */
Yukari.prototype._initRow = function(row, useOrigName) {
    for(var i = 0; i < this.$fields.length; i++) {
        var field = this.$fields[i];
        var name = useOrigName ? field.column : field.name;
        if(undefined === row[name]) {
            continue;
        }

        this.$origData[field.name] = {
            fieldIdx : i,
            data     : row[name] === null ? null : field.type.parse(row[name])
        };
    }

    for(var key in this.$origData) {
        if(!this.$origData.hasOwnProperty(key)) {
            continue;
        }

        this[key] = Object.clone(this.$origData[key].data, true);
    }

    if(row.$fromCache) {
        this.$fromCache = true;
    }
};

/**
 * to json object
 * @param [old]
 * @returns {{}}
 */
Yukari.prototype.toJSON = function(old) {
    var obj = old ? this.$origData : this;
    var result = {};
    for(var key in obj) {
        if(key.length && key[0] !== "$" && typeof obj[key] !== "function") {
            result[key] = obj[key];

            // if it has a certain `toJSON` function
            var idx = this._fieldAt(key);
            if(idx !== -1 && typeof this.$fields[idx].type.toJSON === "function") {
                result[key] = this.$fields[idx].type.toJSON(result[key]);
            }
        }
    }

    return result;
};

/**
 * field at
 * @param name
 * @returns {*}
 * @private
 */
Yukari.prototype._fieldAt = function(name) {
    if(this.$source !== "new" && this.$origData[name]) {
        return this.$origData[name].fieldIdx;
    } else if(this.$source === "new") {
        for(var i = 0; i < this.$fields.length; i++) {
            if(this.$fields[i].name === name) {
                return i;
            }
        }
    }

    return -1;
};

/**
 * validate all fields
 * @returns {*}
 */
Yukari.prototype.validateAll = function() {
    for(var key in this) {
        if(!this.hasOwnProperty(key)) {
            continue;
        }

        if(key[0] === "$" ||
            typeof this[key] === "function" ||
            this._fieldAt(key) === -1) {
            continue;
        }

        var result = this.validateOne(key, this[key]);
        if(typeof result === "string" && result.length) {
            return result;
        }
    }

    return "";
};

/**
 * validate one field
 * @param name
 * @param value
 * @returns {*}
 */
Yukari.prototype.validateOne = function(name, value) {
    var fieldIdx = this._fieldAt(name);
    if(-1 === fieldIdx) {
        return "No such field.";
    }

    var field = this.$fields[fieldIdx];

    if(null === value && !field.allowNull) {
        return "Field " + name + " can't be NULL.";
    } else if(null === value && field.allowNull) {
        return "";
    }

    for(var i = 0; i < field.validators.length; i++) {
        var result = field.validators[i](value);
        if(typeof result === "string" && result.length) {
            return result;
        }
    }

    return "";
};

/**
 * insert a record
 * @param callback
 * @returns {*}
 */
Yukari.prototype.insert = function(callback) {
    var promise = new ResultPromisor();
    if(callback === undefined) {
        callback = function() {};
    }

    if(this.$source !== "new") {
        callback(new Error(
            "You must call this function via a new Yukari object."));

        promise._onExecuteResult(new Error(
            "You must call this function via a new Yukari object."));

        return promise;
    }

    var vldt = this.validateAll();
    if(vldt.length) {
        callback(new Error(vldt));
        promise._onExecuteResult(new Error(vldt));
        return promise;
    }

    var data = {};
    for(var key in this) {
        if(!this.hasOwnProperty(key)) {
            continue;
        }

        if(key[0] === "$") {
            continue;
        }

        var fieldIdx = this._fieldAt(key);

        if(-1 === fieldIdx) {
            continue;
        }

        var field = this.$fields[fieldIdx];
        if(this[key] !== null) {
            data[field.column] = field.type.restore(this[key]);
        } else {
            this[key] = null;
        }
    }

    var sql = util.format("INSERT INTO `%s` SET ?", this.$model.name);
    sql = mysql.format(sql, data);

    if(this.$toshihiko.options.showSql) {
        console.log("❤ Toshihiko is executing SQL: 【" + sql + "】...");
    }

    var self = this;
    this.$toshihiko.execute(sql, function(err, row) {
        if(err) {
            callback(err, undefined, sql);
            promise._onExecuteResult(err, undefined, sql);
            return promise;
        }

        if(!row) {
            callback(new Error("No row inserted."), undefined, sql);
            promise._onExecuteResult(
                new Error("No row inserted."),
                undefined,
                sql);
            return promise;

        }

        self.$source = "query";

        var where = {};
        var pk = self.$model.primaryKeys;
        if(row.insertId) {
            where[pk[0].name] = row.insertId;
        } else {
            for(var i = 0; i < self.$model.primaryKeys.length; i++) {
                where[pk[0].name] = self[pk[0].name];
            }
        }

        self.$model.where(where).findOne(function(err, row) {
            if(err) {
                callback(new Error(
                    "Insert successfully but failed to read the record: " + err.message));
                promise._onExecuteResult(new Error(
                    "Insert successfully but failed to read the record: " + err.message));
                return promise;
            }

            if(!row) {
                callback(new Error(
                    "Insert successfully but failed to read the record: Unknown error."));
                promise._onExecuteResult(new Error(
                    "Insert successfully but failed to read the record: Unknown error."));
                return promise;
            }

            for(var key in row) {
                if(!row.hasOwnProperty(key)) {
                    continue;
                }

                if(key[0] === "$" && key !== "$origData") {
                    continue;
                }

                if(typeof row[key] === "function") {
                    continue;
                }

                self[key] = 囍.clone(row[key], true);
            }

            callback(undefined, self, sql);
            promise._onExecuteResult(undefined, self, sql);
        });
    });
    return promise;
};

/**
 * updata a record
 * @param callback
 * @returns {*}
 */
Yukari.prototype.update = function(callback) {
    var promise = new ResultPromisor();
    if(undefined === callback) {
        callback = function() {};
    }

    if(this.$source !== "query") {
        callback(new Error(
            "You must call this function via a Yukari object which is queried."));
        promise._onExecuteResult(new Error(
            "You must call this function via a Yukari object which is queried."));
        return promise;
    }

    var vldt = this.validateAll();
    if(vldt.length) {
        callback(new Error(vldt));
        promise._onExecuteResult(new Error(vldt));
        return promise;
    }

    var data = {};

    for(var key in this) {
        if(!this.hasOwnProperty(key)) {
            continue;
        }

        if(key[0] === "$") {
            continue;
        }

        if(typeof this[key] === "function") {
            continue;
        }

        var fieldIdx = this._fieldAt(key);
        if(-1 === fieldIdx) {
            continue;
        }

        var field = this.$fields[fieldIdx];
        var equalFunc = ((undefined === field.type.equal) ?
            fieldType.$equal.bind(fieldType) :
            field.type.equal.bind(field.type));

        // only change changed data
        if(!equalFunc(this[key], this.$origData[key].data)) {
            data[field.name] = {
                data    : this[key],
                field   : field
            };
        }
    }

    if(!囍.size(data)) {
        callback(new Error("No data changed."));
        promise._onExecuteResult(new Error("No data changed."));
        return promise;
    }

    // set data
    var sql = "UPDATE `%s` SET ?";
    var finalData = {};
    for(var key in data) {
        if(!data.hasOwnProperty(key)) continue;

        var n2c = this.$model._fieldsKeyMap.n2c[key];
        if(data[key].data !== null) {
            finalData[n2c] = data[key].field.type.restore(data[key].data);
        } else {
            finalData[n2c] = null;
        }
    }

    sql = util.format(sql, this.$model.name);
    sql = mysql.format(sql, finalData) + " WHERE ";

    // set primary key condition
    var conditionSql = "";
    var pk = [];
    for(var i = 0; i < this.$model.primaryKeys.length; i++) {
        var p = this.$model.primaryKeys[i];
        if(pk.length) {
            conditionSql += " AND ";
        }

        conditionSql += "`" + p.column + "` = ?";

        pk.push(p.type.restore(this.$origData[p.name].data));
    }
    sql += mysql.format(conditionSql, pk);

    if(this.$toshihiko.options.showSql) {
        console.log("❤ Toshihiko is executing SQL: 【" + sql + "】...");
    }

    var self = this;
    async.waterfall([
        /**
         * step 1.
         *   if cache...
         * @param callback
         */
        function(callback) {
            if(!self.$cache) {
                return callback();
            }

            var primary = self._getPrimaryKeys(true);
            if(typeof primary === "object") {
                self.$model.nameToColumn(primary);
            }

            self.$cache.deleteData(
                self.$dbName,
                self.$tableName,
                primary,
                function(err) {
                    callback(err);
                });
        },

        /**
         * step 2.
         *   edit 本体...
         * @param callback
         */
        function(callback) {
            self.$toshihiko.execute(sql, function(err, results) {
                if(err) {
                    return callback(err);
                }

                if(!results.affectedRows) {
                    return callback(new Error("No row(s) effected."));
                }

                for(var key in data) {
                    if(!data.hasOwnProperty(key)) {
                        continue;
                    }

                    var d = data[key];
                    self.$origData[d.field.name].data = d.data;
                }
                self.$source = "query";

                callback();
            });
        }
    ], function(err) {
        callback(err, self, sql);
        promise._onExecuteResult(err, self, sql);
    });
    return promise;
};

/**
 * delete this yukari
 * @param callback
 * @returns {*}
 */
Yukari.prototype.delete = function(callback) {
    var promise = new ResultPromisor();
    if(undefined === callback) {
        callback = function(){};
    }

    if(this.$source === "new") {
        callback(new Error("You must delete a queried record."));
        promise._onExecuteResult(new Error("You must delete a queried record."));
        return promise;
    }

    var pk = {};
    for(var i = 0; i < this.$model.primaryKeys.length; i++) {
        var field = this.$model.primaryKeys[i];
        pk[field.name] = this.$origData[field.name].data;
    }

    /**
     * Model::where -> new Query
     * Query::delete 已经有做对 CACHE 的处理，无需多处理
     */
    this.$model.where(pk).limit("0,1").delete(function(err, result, sql) {
        if(err) {
            callback(err, undefined, sql);
            promise._onExecuteResult(err, undefined, sql);
        }

        callback(undefined, result.affectedRows, sql);
        promise._onExecuteResult(undefined, result.affectedRows, sql);
    });
    return promise;
};

/**
 * save / insert a record
 * @param callback
 */
Yukari.prototype.save = function(callback) {
    if(undefined === callback) {
        callback = function() {};
    }

    if(this.$source === "query") {
        return this.update(callback);
    } else if(this.$source === "new") {
        return this.insert(callback);
    }
};

module.exports = Yukari;
<commit_msg>fix some bugs while removing sugar again<commit_after>/**
 * XadillaX created at 2014-09-09 14:21
 *
 * Copyright (c) 2014 Huaban.com, all rights
 * reserved.
 */
"use strict";

var 囍 = require("lodash");
var util = require("util");
var mysql = require("mysql2");
var async = require("async");
var fieldType = require("./fieldType");
var ResultPromisor = require("./resultpromisor");

/**
 * Yakumo Yukari is the entity of Yakumo Toshihiko.
 * @param model
 * @param source
 * @constructor
 */
var Yukari = function(model, source) {
    this.$model = model;
    this.$toshihiko = model.toshihiko;

    this.$fields = model._fieldsObject;
    this.$origData = {};

    this.$source = source;

    this.$dbName = this.$toshihiko.database;
    this.$tableName = this.$model.name;
    this.$cache = model.cache;

    this.$fromCache = false;
};

/**
 * get primary keys and values
 * @param {Boolean} [fromOrig] is primary keys from original data
 * @returns {*}
 * @private
 */
Yukari.prototype._getPrimaryKeys = function(fromOrig) {
    var keys = this.$model.getPrimaryKeysName();
    if(typeof keys === "string") {
        return (fromOrig || this[keys] === undefined) ?
            this.$origData[keys] :
            this[keys];
    }

    var obj = {};
    for(var i = 0; i < keys.length; i++) {
        obj[keys[i]] = (fromOrig || this[keys[i]] === undefined) ?
            this.$origData[keys[i]] :
            this[keys[i]];
    }
    return obj;
};

/**
 * build row
 * @param row
 * @param useOrigName
 * @private
 */
Yukari.prototype._buildRow = function(row, useOrigName) {
    this.$origData = {};

    for(var i = 0; i < this.$fields.length; i++) {
        var field = this.$fields[i];
        var value = row[useOrigName ? field.column : field.name];

        if(undefined === value) {
            if(undefined !== field.defaultValue) {
                value = field.defaultValue;
            }
        }

        if(undefined === value) {
            continue;
        }

        this[field.name] = 囍.clone(value);
    }

    if(row.$fromCache) {
        this.$fromCache = true;
    }
};

/**
 * initialize row
 * @param row
 * @param useOrigName
 * @private
 */
Yukari.prototype._initRow = function(row, useOrigName) {
    for(var i = 0; i < this.$fields.length; i++) {
        var field = this.$fields[i];
        var name = useOrigName ? field.column : field.name;
        if(undefined === row[name]) {
            continue;
        }

        this.$origData[field.name] = {
            fieldIdx : i,
            data     : row[name] === null ? null : field.type.parse(row[name])
        };
    }

    for(var key in this.$origData) {
        if(!this.$origData.hasOwnProperty(key)) {
            continue;
        }

        this[key] = 囍.clone(this.$origData[key].data, true);
    }

    if(row.$fromCache) {
        this.$fromCache = true;
    }
};

/**
 * to json object
 * @param [old]
 * @returns {{}}
 */
Yukari.prototype.toJSON = function(old) {
    var obj = old ? this.$origData : this;
    var result = {};
    for(var key in obj) {
        if(key.length && key[0] !== "$" && typeof obj[key] !== "function") {
            result[key] = obj[key];

            // if it has a certain `toJSON` function
            var idx = this._fieldAt(key);
            if(idx !== -1 && typeof this.$fields[idx].type.toJSON === "function") {
                result[key] = this.$fields[idx].type.toJSON(result[key]);
            }
        }
    }

    return result;
};

/**
 * field at
 * @param name
 * @returns {*}
 * @private
 */
Yukari.prototype._fieldAt = function(name) {
    if(this.$source !== "new" && this.$origData[name]) {
        return this.$origData[name].fieldIdx;
    } else if(this.$source === "new") {
        for(var i = 0; i < this.$fields.length; i++) {
            if(this.$fields[i].name === name) {
                return i;
            }
        }
    }

    return -1;
};

/**
 * validate all fields
 * @returns {*}
 */
Yukari.prototype.validateAll = function() {
    for(var key in this) {
        if(!this.hasOwnProperty(key)) {
            continue;
        }

        if(key[0] === "$" ||
            typeof this[key] === "function" ||
            this._fieldAt(key) === -1) {
            continue;
        }

        var result = this.validateOne(key, this[key]);
        if(typeof result === "string" && result.length) {
            return result;
        }
    }

    return "";
};

/**
 * validate one field
 * @param name
 * @param value
 * @returns {*}
 */
Yukari.prototype.validateOne = function(name, value) {
    var fieldIdx = this._fieldAt(name);
    if(-1 === fieldIdx) {
        return "No such field.";
    }

    var field = this.$fields[fieldIdx];

    if(null === value && !field.allowNull) {
        return "Field " + name + " can't be NULL.";
    } else if(null === value && field.allowNull) {
        return "";
    }

    for(var i = 0; i < field.validators.length; i++) {
        var result = field.validators[i](value);
        if(typeof result === "string" && result.length) {
            return result;
        }
    }

    return "";
};

/**
 * insert a record
 * @param callback
 * @returns {*}
 */
Yukari.prototype.insert = function(callback) {
    var promise = new ResultPromisor();
    if(callback === undefined) {
        callback = function() {};
    }

    if(this.$source !== "new") {
        callback(new Error(
            "You must call this function via a new Yukari object."));

        promise._onExecuteResult(new Error(
            "You must call this function via a new Yukari object."));

        return promise;
    }

    var vldt = this.validateAll();
    if(vldt.length) {
        callback(new Error(vldt));
        promise._onExecuteResult(new Error(vldt));
        return promise;
    }

    var data = {};
    for(var key in this) {
        if(!this.hasOwnProperty(key)) {
            continue;
        }

        if(key[0] === "$") {
            continue;
        }

        var fieldIdx = this._fieldAt(key);

        if(-1 === fieldIdx) {
            continue;
        }

        var field = this.$fields[fieldIdx];
        if(this[key] !== null) {
            data[field.column] = field.type.restore(this[key]);
        } else {
            this[key] = null;
        }
    }

    var sql = util.format("INSERT INTO `%s` SET ?", this.$model.name);
    sql = mysql.format(sql, data);

    if(this.$toshihiko.options.showSql) {
        console.log("❤ Toshihiko is executing SQL: 【" + sql + "】...");
    }

    var self = this;
    this.$toshihiko.execute(sql, function(err, row) {
        if(err) {
            callback(err, undefined, sql);
            promise._onExecuteResult(err, undefined, sql);
            return promise;
        }

        if(!row) {
            callback(new Error("No row inserted."), undefined, sql);
            promise._onExecuteResult(
                new Error("No row inserted."),
                undefined,
                sql);
            return promise;

        }

        self.$source = "query";

        var where = {};
        var pk = self.$model.primaryKeys;
        if(row.insertId) {
            where[pk[0].name] = row.insertId;
        } else {
            for(var i = 0; i < self.$model.primaryKeys.length; i++) {
                where[pk[0].name] = self[pk[0].name];
            }
        }

        self.$model.where(where).findOne(function(err, row) {
            if(err) {
                callback(new Error(
                    "Insert successfully but failed to read the record: " + err.message));
                promise._onExecuteResult(new Error(
                    "Insert successfully but failed to read the record: " + err.message));
                return promise;
            }

            if(!row) {
                callback(new Error(
                    "Insert successfully but failed to read the record: Unknown error."));
                promise._onExecuteResult(new Error(
                    "Insert successfully but failed to read the record: Unknown error."));
                return promise;
            }

            for(var key in row) {
                if(!row.hasOwnProperty(key)) {
                    continue;
                }

                if(key[0] === "$" && key !== "$origData") {
                    continue;
                }

                if(typeof row[key] === "function") {
                    continue;
                }

                self[key] = 囍.clone(row[key], true);
            }

            callback(undefined, self, sql);
            promise._onExecuteResult(undefined, self, sql);
        });
    });
    return promise;
};

/**
 * updata a record
 * @param callback
 * @returns {*}
 */
Yukari.prototype.update = function(callback) {
    var promise = new ResultPromisor();
    if(undefined === callback) {
        callback = function() {};
    }

    if(this.$source !== "query") {
        callback(new Error(
            "You must call this function via a Yukari object which is queried."));
        promise._onExecuteResult(new Error(
            "You must call this function via a Yukari object which is queried."));
        return promise;
    }

    var vldt = this.validateAll();
    if(vldt.length) {
        callback(new Error(vldt));
        promise._onExecuteResult(new Error(vldt));
        return promise;
    }

    var data = {};

    for(var key in this) {
        if(!this.hasOwnProperty(key)) {
            continue;
        }

        if(key[0] === "$") {
            continue;
        }

        if(typeof this[key] === "function") {
            continue;
        }

        var fieldIdx = this._fieldAt(key);
        if(-1 === fieldIdx) {
            continue;
        }

        var field = this.$fields[fieldIdx];
        var equalFunc = ((undefined === field.type.equal) ?
            fieldType.$equal.bind(fieldType) :
            field.type.equal.bind(field.type));

        // only change changed data
        if(!equalFunc(this[key], this.$origData[key].data)) {
            data[field.name] = {
                data    : this[key],
                field   : field
            };
        }
    }

    if(!囍.size(data)) {
        callback(new Error("No data changed."));
        promise._onExecuteResult(new Error("No data changed."));
        return promise;
    }

    // set data
    var sql = "UPDATE `%s` SET ?";
    var finalData = {};
    for(var key in data) {
        if(!data.hasOwnProperty(key)) continue;

        var n2c = this.$model._fieldsKeyMap.n2c[key];
        if(data[key].data !== null) {
            finalData[n2c] = data[key].field.type.restore(data[key].data);
        } else {
            finalData[n2c] = null;
        }
    }

    sql = util.format(sql, this.$model.name);
    sql = mysql.format(sql, finalData) + " WHERE ";

    // set primary key condition
    var conditionSql = "";
    var pk = [];
    for(var i = 0; i < this.$model.primaryKeys.length; i++) {
        var p = this.$model.primaryKeys[i];
        if(pk.length) {
            conditionSql += " AND ";
        }

        conditionSql += "`" + p.column + "` = ?";

        pk.push(p.type.restore(this.$origData[p.name].data));
    }
    sql += mysql.format(conditionSql, pk);

    if(this.$toshihiko.options.showSql) {
        console.log("❤ Toshihiko is executing SQL: 【" + sql + "】...");
    }

    var self = this;
    async.waterfall([
        /**
         * step 1.
         *   if cache...
         * @param callback
         */
        function(callback) {
            if(!self.$cache) {
                return callback();
            }

            var primary = self._getPrimaryKeys(true);
            if(typeof primary === "object") {
                self.$model.nameToColumn(primary);
            }

            self.$cache.deleteData(
                self.$dbName,
                self.$tableName,
                primary,
                function(err) {
                    callback(err);
                });
        },

        /**
         * step 2.
         *   edit 本体...
         * @param callback
         */
        function(callback) {
            self.$toshihiko.execute(sql, function(err, results) {
                if(err) {
                    return callback(err);
                }

                if(!results.affectedRows) {
                    return callback(new Error("No row(s) effected."));
                }

                for(var key in data) {
                    if(!data.hasOwnProperty(key)) {
                        continue;
                    }

                    var d = data[key];
                    self.$origData[d.field.name].data = d.data;
                }
                self.$source = "query";

                callback();
            });
        }
    ], function(err) {
        callback(err, self, sql);
        promise._onExecuteResult(err, self, sql);
    });
    return promise;
};

/**
 * delete this yukari
 * @param callback
 * @returns {*}
 */
Yukari.prototype.delete = function(callback) {
    var promise = new ResultPromisor();
    if(undefined === callback) {
        callback = function(){};
    }

    if(this.$source === "new") {
        callback(new Error("You must delete a queried record."));
        promise._onExecuteResult(new Error("You must delete a queried record."));
        return promise;
    }

    var pk = {};
    for(var i = 0; i < this.$model.primaryKeys.length; i++) {
        var field = this.$model.primaryKeys[i];
        pk[field.name] = this.$origData[field.name].data;
    }

    /**
     * Model::where -> new Query
     * Query::delete 已经有做对 CACHE 的处理，无需多处理
     */
    this.$model.where(pk).limit("0,1").delete(function(err, result, sql) {
        if(err) {
            callback(err, undefined, sql);
            promise._onExecuteResult(err, undefined, sql);
        }

        callback(undefined, result.affectedRows, sql);
        promise._onExecuteResult(undefined, result.affectedRows, sql);
    });
    return promise;
};

/**
 * save / insert a record
 * @param callback
 */
Yukari.prototype.save = function(callback) {
    if(undefined === callback) {
        callback = function() {};
    }

    if(this.$source === "query") {
        return this.update(callback);
    } else if(this.$source === "new") {
        return this.insert(callback);
    }
};

module.exports = Yukari;
<|endoftext|>


<commit_before>import {
  requestUrl,
  isAValidWorld,
  getTibiaWorlds,
  getOnlinePlayersByWorld,
  getCharacterInformationByName,
  getCharacterDeathInformationByName,
} from './utils';

class TibiaAPI {
  constructor(props) {
    if (props && props.worldName) {
      this.worldName = props.worldName;
    }
  }

  getOnlinePlayers(worldName) {
    return new Promise((resolve, reject) => {
      let worldNameToUse = worldName ? worldName : this.world;
      if (!worldNameToUse) {
        console.warn('No Game word passed');
        return;
      }
      isAValidWorld(worldNameToUse).then((isValid) => {
        if (isValid) {
          getOnlinePlayersByWorld(worldNameToUse).then((result) => {
            console.log(result);
          }).catch((error) => console.log(error))
        } else {
          reject(`${worldNameToUse} is not a valud Server World`);
        }
      }).catch((error) => reject(error));
    });
  }

  getCharacterInformation(characterName) {
    if (!characterName) {
      console.warn('Characte rname is needed');
      returnl;
    };
    return new Promise((resolve, reject) => {
      getCharacterInformationByName(characterName).then((result) => {
        resolve(result);
      }).catch((error) => reject(error));
    });
  }

  getCharacterDeathInformation(characterName) {
    if (!characterName) {
      console.warn('Charactername is needed');
      return;
    };
    return new Promise((resolve, reject) => {
      getCharacterDeathInformationByName(characterName).then((result) => {
        resolve(result);
      }).catch((error) => reject(error));
    });
  }
}

const tibia = new TibiaAPI({ worldName: 'Zanera'});

tibia.getCharacterInformation('Diegopump').then((result) => console.log(result));

export default TibiaAPI;
<commit_msg>minor fix<commit_after>import {
  requestUrl,
  isAValidWorld,
  getTibiaWorlds,
  getOnlinePlayersByWorld,
  getCharacterInformationByName,
  getCharacterDeathInformationByName,
} from './utils';

class TibiaAPI {
  constructor(props) {
    if (props && props.worldName) {
      this.worldName = props.worldName;
    }
  }

  getOnlinePlayers(worldName) {
    return new Promise((resolve, reject) => {
      let worldNameToUse = worldName ? worldName : this.world;
      if (!worldNameToUse) {
        console.warn('No Game word passed');
        return;
      }
      isAValidWorld(worldNameToUse).then((isValid) => {
        if (isValid) {
          getOnlinePlayersByWorld(worldNameToUse).then((result) => {
            console.log(result);
          }).catch((error) => console.log(error))
        } else {
          reject(`${worldNameToUse} is not a valud Server World`);
        }
      }).catch((error) => reject(error));
    });
  }

  getCharacterInformation(characterName) {
    if (!characterName) {
      console.warn('Characte rname is needed');
      returnl;
    };
    return new Promise((resolve, reject) => {
      getCharacterInformationByName(characterName).then((result) => {
        resolve(result);
      }).catch((error) => reject(error));
    });
  }

  getCharacterDeathInformation(characterName) {
    if (!characterName) {
      console.warn('Charactername is needed');
      return;
    };
    return new Promise((resolve, reject) => {
      getCharacterDeathInformationByName(characterName).then((result) => {
        resolve(result);
      }).catch((error) => reject(error));
    });
  }
}

export default TibiaAPI;
<|endoftext|>


<commit_before>// @flow

import { mainStory, addListener } from 'storyboard';
import consoleListener from 'storyboard-listener-console';
import wsServerListener from 'storyboard-listener-ws-server';
import program from 'commander';
import opn from 'opn';
import * as db from './db';
import { init as gqlInit } from './graphql/gqlServer';
import { init as httpInit } from './httpServer';
import { init as socketInit } from './socketServer';

const pkg = require('../../package.json');

const DEFAULT_LOCALE_PATH = 'locales';
const DEFAULT_PORT = 8080;

addListener(consoleListener);
process.on('SIGINT', () => {
  mainStory.debug('startup', 'CTRL-C received');
  process.exit(0);
});

// ==============================================
// Main
// ==============================================
program
  .version(pkg.version)
  .option(
    '-d, --dir [dir]',
    'Relative path to locale folder',
    DEFAULT_LOCALE_PATH
  )
  .option(
    '-p, --port [port]',
    'Initial port number to use ' +
      '(if unavailable, the next available one will be used)',
    Number,
    DEFAULT_PORT
  )
  .option('--recompile', 'Recompile translations upon launch')
  .option('--importV0 [dir]', 'Import a "v0" (old) locale folder')
  .parse(process.argv);

const cliOptions = program.opts();

mainStory.info('startup', 'CLI options:', { attach: cliOptions });
db.init({ localeDir: cliOptions.dir, fRecompile: cliOptions.recompile });
if (cliOptions.importV0) {
  db.importV0(cliOptions.importV0);
} else {
  const gqlSchema = gqlInit();
  const httpServer = httpInit({ port: cliOptions.port });
  const socketServer = socketInit({ httpServer, gqlSchema });
  addListener(wsServerListener, { socketServer });
}
opn(`http://localhost:${cliOptions.port}/`);
<commit_msg>Minor<commit_after>// @flow

import { mainStory, addListener } from 'storyboard';
import consoleListener from 'storyboard-listener-console';
import wsServerListener from 'storyboard-listener-ws-server';
import program from 'commander';
import opn from 'opn';
import * as db from './db';
import { init as gqlInit } from './graphql/gqlServer';
import { init as httpInit } from './httpServer';
import { init as socketInit } from './socketServer';

const pkg = require('../../package.json');

const DEFAULT_LOCALE_PATH = 'locales';
const DEFAULT_PORT = 8080;

addListener(consoleListener);
process.on('SIGINT', () => {
  mainStory.debug('startup', 'CTRL-C received');
  process.exit(0);
});

process.on('unhandledRejection', err => {
  console.error(err); // eslint-disable-line
  process.exit(1);
});

// ==============================================
// Main
// ==============================================
program
  .version(pkg.version)
  .option(
    '-d, --dir [dir]',
    'Relative path to locale folder',
    DEFAULT_LOCALE_PATH
  )
  .option(
    '-p, --port [port]',
    'Initial port number to use ' +
      '(if unavailable, the next available one will be used)',
    Number,
    DEFAULT_PORT
  )
  .option('--recompile', 'Recompile translations upon launch')
  .option('--importV0 [dir]', 'Import a "v0" (old) locale folder')
  .parse(process.argv);

const cliOptions = program.opts();

mainStory.info('startup', 'CLI options:', { attach: cliOptions });
db.init({ localeDir: cliOptions.dir, fRecompile: cliOptions.recompile });
if (cliOptions.importV0) {
  db.importV0(cliOptions.importV0);
} else {
  const gqlSchema = gqlInit();
  const httpServer = httpInit({ port: cliOptions.port });
  const socketServer = socketInit({ httpServer, gqlSchema });
  addListener(wsServerListener, { socketServer });
}
opn(`http://localhost:${cliOptions.port}/`).catch(err => {
  mainStory.error('OPN error', { attach: err });
});
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';

Meteor.startup(() => {
	process.env.MAIL_URL = 'urlgoeshere';
})<commit_msg>fixes<commit_after>import { Meteor } from 'meteor/meteor';

Meteor.startup(() => {

})<|endoftext|>


<commit_before>/* eslint-disable */
// TODO: do we need to manually clear cache when we upgrade cacheName?
var cacheName = 'modsplus-1';
importScripts('/sw-toolbox.js');

// toolbox.options.debug = true;
toolbox.precache(['/manifest.json', '/assets/main.js']);

// TODO: think about how we want to handle other routes
// toolbox.router.default = toolbox.networkOnly;

// we use query busting to fetch new main.js
toolbox.router.get('/assets/main.js', toolbox.cacheFirst);

toolbox.router.get('/manifest.json', toolbox.networkFirst);
toolbox.router.get('/graphql', toolbox.networkFirst);
toolbox.router.get('/api', toolbox.networkFirst);
toolbox.router.get('/', toolbox.networkFirst);
// /* eslint-enable */
<commit_msg>Cache group.png<commit_after>/* eslint-disable */
// TODO: do we need to manually clear cache when we upgrade cacheName?
var cacheName = 'modsplus-1';
importScripts('/sw-toolbox.js');

// toolbox.options.debug = true;
toolbox.precache(['/manifest.json', '/assets/main.js', '/group.png']);

// TODO: think about how we want to handle other routes
// toolbox.router.default = toolbox.networkOnly;

// we use query busting to fetch new main.js
toolbox.router.get('/assets/main.js', toolbox.cacheFirst);
toolbox.router.get('/group.png', toolbox.cacheFirst);

toolbox.router.get('/manifest.json', toolbox.networkFirst);
toolbox.router.get('/graphql', toolbox.networkFirst);
toolbox.router.get('/api', toolbox.networkFirst);
toolbox.router.get('/', toolbox.networkFirst);
// /* eslint-enable */
<|endoftext|>


<commit_before>/* global MarkerClusterer: true, google: true */
(function() {
    "use strict";

    angular.module('hippo.theme')

    /**
     * @ngdoc directive
     * @name hippo.theme.directive:map
     * @restrict A
     *
     * @description
     * Uses Google Maps to display a map with the markers provided.
     * The markers are grouped when they are close to each other.
     *
     * @scope
     * @param {Array} points A list of points to be visualised, each having a longitude and latitude property
     */
    .directive('map', [

        function() {
            return {
                restrict: 'A',
                scope: {
                    points: '=markers'
                },
                link: function(scope, elem, attrs) {
                    // map options
                    var latlng = new google.maps.LatLng(52.359448, 4.901317);
                    var options = {
                        zoom: 8,
                        mapTypeId: google.maps.MapTypeId.ROADMAP,
                        center: latlng
                    };
                    var map = new google.maps.Map(elem[0], options);
                    var markerCluster = new MarkerClusterer(map, []);

                    scope.$watch('points', function(points) {
                        // points to Google latLng objects
                        var latLngList = _.map(points, function(point) {
                            return new google.maps.LatLng(point.latitude, point.longitude);
                        });

                        // (re)draw map with markers
                        drawMarkers(latLngList);
                    });

                    function drawMarkers(latLngList) {
                        // create markers
                        var markers = _.map(latLngList, function(latLng) {
                            return new google.maps.Marker({
                                'position': latLng
                            });
                        });

                        // add markers to map
                        markerCluster.clearMarkers();
                        markerCluster.addMarkers(markers);
                        markerCluster.redraw();

                        // map viewpoint based on all markers
                        var bounds = new google.maps.LatLngBounds();
                        angular.forEach(latLngList, function(latLng) {
                            bounds.extend(latLng);
                        });

                        if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
                            var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.015, bounds.getNorthEast().lng() + 0.015);
                            var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - 0.015, bounds.getNorthEast().lng() - 0.015);
                            bounds.extend(extendPoint1);
                            bounds.extend(extendPoint2);
                        }

                        //  fit these bounds to the map
                        map.fitBounds(bounds);
                    }
                }
            };
        }
    ]);
})();<commit_msg>RD-1996 Improved description for the Map component<commit_after>/* global MarkerClusterer: true, google: true */
(function() {
    "use strict";

    angular.module('hippo.theme')

    /**
     * @ngdoc directive
     * @name hippo.theme.directive:map
     * @restrict A
     *
     * @description
     * Uses Google Maps to display a map with the markers provided.
     * The markers are grouped when they are close to each other.
     *
     * @scope
     * @param {Array} points A list of point objects, having a longitude- and latitude property, to be visualised. Each having a longitude and latitude property.
     */
    .directive('map', [

        function() {
            return {
                restrict: 'A',
                scope: {
                    points: '=markers'
                },
                link: function(scope, elem, attrs) {
                    // map options
                    var latlng = new google.maps.LatLng(52.359448, 4.901317);
                    var options = {
                        zoom: 8,
                        mapTypeId: google.maps.MapTypeId.ROADMAP,
                        center: latlng
                    };
                    var map = new google.maps.Map(elem[0], options);
                    var markerCluster = new MarkerClusterer(map, []);

                    scope.$watch('points', function(points) {
                        // points to Google latLng objects
                        var latLngList = _.map(points, function(point) {
                            return new google.maps.LatLng(point.latitude, point.longitude);
                        });

                        // (re)draw map with markers
                        drawMarkers(latLngList);
                    });

                    function drawMarkers(latLngList) {
                        // create markers
                        var markers = _.map(latLngList, function(latLng) {
                            return new google.maps.Marker({
                                'position': latLng
                            });
                        });

                        // add markers to map
                        markerCluster.clearMarkers();
                        markerCluster.addMarkers(markers);
                        markerCluster.redraw();

                        // map viewpoint based on all markers
                        var bounds = new google.maps.LatLngBounds();
                        angular.forEach(latLngList, function(latLng) {
                            bounds.extend(latLng);
                        });

                        if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
                            var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.015, bounds.getNorthEast().lng() + 0.015);
                            var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - 0.015, bounds.getNorthEast().lng() - 0.015);
                            bounds.extend(extendPoint1);
                            bounds.extend(extendPoint2);
                        }

                        //  fit these bounds to the map
                        map.fitBounds(bounds);
                    }
                }
            };
        }
    ]);
})();<|endoftext|>


<commit_before>$.register({
  rule: {
    host: /^(imgwiev|www\.imgjav)\.tk|www\.x45x\.info|(imadul|mypixxx\.lonestarnaughtygirls)\.com|ghanaimages\.co|imgurban\.info|d69\.in|www\.images\.woh\.to$/,
    query: /\?p[mt]=(.+)/,
  },
  start: function (m) {
    'use strict';

    $.openImage('/?di=' + m.query[1]);
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>imgwiev.tk<commit_after>$.register({
  rule: {
    host: /^www\.imgjav\.tk|www\.x45x\.info|(imadul|mypixxx\.lonestarnaughtygirls)\.com|ghanaimages\.co|imgurban\.info|d69\.in|www\.images\.woh\.to$/,
    query: /\?p[mt]=(.+)/,
  },
  start: function (m) {
    'use strict';

    $.openImage('/?di=' + m.query[1]);
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>import {getNestedProperty} from 'get-nested-property';

/**
 * Finds value in global namespace.
 * @param {string} path - Dot separated path to value in global namespace.
 * @param {Array} parameters
 * @returns {*}
 */
export default function (path = '', parameters = []) {
  const root = window || global;
  const result = getNestedProperty(root, path);
  return typeof result === 'function'
    ? result.apply(null, parameters)
    : result;
}
<commit_msg>refactor: remove unused variable<commit_after>import {getNestedProperty} from 'get-nested-property';

/**
 * Finds value in global namespace.
 * @param {string} path - Dot separated path to value in global namespace.
 * @param {Array} parameters
 * @returns {*}
 */
export default function (path = '', parameters = []) {
  const root = window;
  const result = getNestedProperty(root, path);
  return typeof result === 'function'
    ? result.apply(null, parameters)
    : result;
}
<|endoftext|>


<commit_before>import path from 'path';
import lodash from 'lodash';
import requirePackageName from 'require-package-name';
import { loadModuleData, wrapToArray } from '../utils';
import { loadConfig } from '../utils/cli-tools';
import { getContent } from '../utils/file';

function resolveConfigModule(preset, rootDir) {
  const presetParts = preset.split('/');
  let moduleName = presetParts.shift();
  if (moduleName.startsWith('@')) {
    moduleName += `/${presetParts.shift()}`;
  }
  const moduleData = loadModuleData(moduleName, rootDir);
  const includedDeps =
    moduleData.metadata &&
    moduleData.metadata.dependencies &&
    typeof moduleData.metadata.dependencies === 'object'
      ? Object.keys(moduleData.metadata.dependencies)
      : [];
  return [
    moduleData.path && path.resolve(moduleData.path, ...presetParts),
    includedDeps,
  ];
}

function requireConfig(preset, rootDir) {
  const [presetPath, includedDeps] = path.isAbsolute(preset)
    ? [preset, []]
    : resolveConfigModule(preset, rootDir);

  try {
    return [require(presetPath), includedDeps]; // eslint-disable-line global-require
  } catch (error) {
    return [{}, []]; // silently return nothing
  }
}

/**
 * Brings package name to correct format based on prefix
 * @param {string} name The name of the package.
 * @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
 * @returns {string} Normalized name of the package
 * @private
 * @see {@link https://github.com/eslint/eslint/blob/faf3c4eda0d27323630d0bc103a99dd0ecffe842/lib/util/naming.js#L25 ESLint}
 */
function normalizePackageName(name, prefix) {
  let normalizedName = name;
  const convertPathToPosix = (p) => path.normalize(p).replace(/\\/g, '/');

  /**
   * On Windows, name can come in with Windows slashes instead of Unix slashes.
   * Normalize to Unix first to avoid errors later on.
   * https://github.com/eslint/eslint/issues/5644
   */
  if (normalizedName.indexOf('\\') > -1) {
    normalizedName = convertPathToPosix(normalizedName);
  }

  if (normalizedName.charAt(0) === '@') {
    /**
     * it's a scoped package
     * package name is the prefix, or just a username
     */
    const scopedPackageShortcutRegex = new RegExp(
      `^(@[^/]+)(?:/(?:${prefix})?)?$`,
    );
    const scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`);

    if (scopedPackageShortcutRegex.test(normalizedName)) {
      normalizedName = normalizedName.replace(
        scopedPackageShortcutRegex,
        `$1/${prefix}`,
      );
    } else if (!scopedPackageNameRegex.test(normalizedName.split('/')[1])) {
      /**
       * for scoped packages, insert the prefix after the first / unless
       * the path is already @scope/eslint or @scope/eslint-xxx-yyy
       */
      normalizedName = normalizedName.replace(
        /^@([^/]+)\/(.*)$/,
        `@$1/${prefix}-$2`,
      );
    }
  } else if (normalizedName.indexOf(`${prefix}-`) !== 0) {
    normalizedName = `${prefix}-${normalizedName}`;
  }

  return normalizedName;
}

function resolvePresetPackage(preset, rootDir) {
  // inspired from https://github.com/eslint/eslint/blob/5b4a94e26d0ef247fe222dacab5749805d9780dd/lib/config/config-file.js#L347
  if (path.isAbsolute(preset)) {
    return preset;
  }
  if (preset.startsWith('./') || preset.startsWith('../')) {
    return path.resolve(rootDir, preset);
  }

  if (preset.startsWith('plugin:')) {
    const pluginName = preset.slice(7, preset.lastIndexOf('/'));
    return normalizePackageName(pluginName, 'eslint-plugin');
  }

  return normalizePackageName(preset, 'eslint-config');
}

function checkConfig(config, rootDir, includedDeps = []) {
  const configs = [config];
  if (config.overrides) {
    configs.push(...config.overrides);
  }

  const parser = configs
    .map((value) => wrapToArray(value.parser))
    .flatMap((value) => value)
    .filter((value) => value !== undefined);

  const plugins = configs
    .map((value) => wrapToArray(value.plugins))
    .filter((value) => value !== undefined)
    .flatMap((value) => value)
    .map((plugin) => normalizePackageName(plugin, 'eslint-plugin'));

  const extendsArray = configs
    .map((value) => wrapToArray(value.extends))
    .filter((value) => value !== undefined)
    .flatMap((value) => value);
  const presets = extendsArray
    .filter((preset) => !['eslint:recommended', 'eslint:all'].includes(preset))
    .map((preset) => resolvePresetPackage(preset, rootDir));

  // prettier/recommended extends eslint-config-prettier
  // https://github.com/prettier/eslint-plugin-prettier#recommended-configuration
  if (extendsArray.includes('plugin:prettier/recommended')) {
    presets.push('eslint-config-prettier');
  }

  const presetPackages = presets
    .filter((preset) => !path.isAbsolute(preset))
    .map(requirePackageName);

  const presetDeps = lodash(presets)
    .map((preset) => requireConfig(preset, rootDir))
    .map(([presetConfig, deps]) => checkConfig(presetConfig, rootDir, deps))
    .flatten()
    .value();

  const result = lodash
    .union(parser, plugins, presetPackages, presetDeps)
    .filter((dep) => !includedDeps.includes(dep));

  configs.forEach((value) => {
    if (value.settings) {
      Object.keys(value.settings).forEach((key) => {
        if (key !== 'import/resolver') {
          return;
        }
        Object.keys(value.settings[key]).forEach((resolverName) => {
          // node and webpack resolvers are included in `eslint-plugin-import`
          if (!['node', 'webpack'].includes(resolverName)) {
            result.push(`eslint-import-resolver-${resolverName}`);
          }
        });
      });
    }
  });

  return result;
}

const configNameRegex = /^\.eslintrc(\.(json|js|yml|yaml))?$/;

export default async function parseESLint(filename, deps, rootDir) {
  const config = await loadConfig('eslint', configNameRegex, filename, rootDir);

  if (config) {
    return checkConfig(config, rootDir);
  }

  const packageJsonPath = path.resolve(rootDir, 'package.json');
  const resolvedFilePath = path.resolve(rootDir, filename);

  if (resolvedFilePath === packageJsonPath) {
    const content = await getContent(filename);
    const parsed = JSON.parse(content);
    if (parsed.eslintConfig) {
      return checkConfig(parsed.eslintConfig, rootDir);
    }
  }

  return [];
}
<commit_msg>fix language level by using lodash<commit_after>import path from 'path';
import lodash from 'lodash';
import requirePackageName from 'require-package-name';
import { loadModuleData, wrapToArray } from '../utils';
import { loadConfig } from '../utils/cli-tools';
import { getContent } from '../utils/file';

function resolveConfigModule(preset, rootDir) {
  const presetParts = preset.split('/');
  let moduleName = presetParts.shift();
  if (moduleName.startsWith('@')) {
    moduleName += `/${presetParts.shift()}`;
  }
  const moduleData = loadModuleData(moduleName, rootDir);
  const includedDeps =
    moduleData.metadata &&
    moduleData.metadata.dependencies &&
    typeof moduleData.metadata.dependencies === 'object'
      ? Object.keys(moduleData.metadata.dependencies)
      : [];
  return [
    moduleData.path && path.resolve(moduleData.path, ...presetParts),
    includedDeps,
  ];
}

function requireConfig(preset, rootDir) {
  const [presetPath, includedDeps] = path.isAbsolute(preset)
    ? [preset, []]
    : resolveConfigModule(preset, rootDir);

  try {
    return [require(presetPath), includedDeps]; // eslint-disable-line global-require
  } catch (error) {
    return [{}, []]; // silently return nothing
  }
}

/**
 * Brings package name to correct format based on prefix
 * @param {string} name The name of the package.
 * @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
 * @returns {string} Normalized name of the package
 * @private
 * @see {@link https://github.com/eslint/eslint/blob/faf3c4eda0d27323630d0bc103a99dd0ecffe842/lib/util/naming.js#L25 ESLint}
 */
function normalizePackageName(name, prefix) {
  let normalizedName = name;
  const convertPathToPosix = (p) => path.normalize(p).replace(/\\/g, '/');

  /**
   * On Windows, name can come in with Windows slashes instead of Unix slashes.
   * Normalize to Unix first to avoid errors later on.
   * https://github.com/eslint/eslint/issues/5644
   */
  if (normalizedName.indexOf('\\') > -1) {
    normalizedName = convertPathToPosix(normalizedName);
  }

  if (normalizedName.charAt(0) === '@') {
    /**
     * it's a scoped package
     * package name is the prefix, or just a username
     */
    const scopedPackageShortcutRegex = new RegExp(
      `^(@[^/]+)(?:/(?:${prefix})?)?$`,
    );
    const scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`);

    if (scopedPackageShortcutRegex.test(normalizedName)) {
      normalizedName = normalizedName.replace(
        scopedPackageShortcutRegex,
        `$1/${prefix}`,
      );
    } else if (!scopedPackageNameRegex.test(normalizedName.split('/')[1])) {
      /**
       * for scoped packages, insert the prefix after the first / unless
       * the path is already @scope/eslint or @scope/eslint-xxx-yyy
       */
      normalizedName = normalizedName.replace(
        /^@([^/]+)\/(.*)$/,
        `@$1/${prefix}-$2`,
      );
    }
  } else if (normalizedName.indexOf(`${prefix}-`) !== 0) {
    normalizedName = `${prefix}-${normalizedName}`;
  }

  return normalizedName;
}

function resolvePresetPackage(preset, rootDir) {
  // inspired from https://github.com/eslint/eslint/blob/5b4a94e26d0ef247fe222dacab5749805d9780dd/lib/config/config-file.js#L347
  if (path.isAbsolute(preset)) {
    return preset;
  }
  if (preset.startsWith('./') || preset.startsWith('../')) {
    return path.resolve(rootDir, preset);
  }

  if (preset.startsWith('plugin:')) {
    const pluginName = preset.slice(7, preset.lastIndexOf('/'));
    return normalizePackageName(pluginName, 'eslint-plugin');
  }

  return normalizePackageName(preset, 'eslint-config');
}

function checkConfig(config, rootDir, includedDeps = []) {
  const configs = [config];
  if (config.overrides) {
    configs.push(...config.overrides);
  }

  const plugins = lodash(configs)
    .map((value) => wrapToArray(value.plugins))
    .flatten()
    .map((plugin) => normalizePackageName(plugin, 'eslint-plugin'))
    .value();

  const parser = lodash(configs)
    .map((value) => wrapToArray(value.parser))
    .flatten()
    .value();

  const extendsArray = lodash(configs)
    .map((value) => wrapToArray(value.extends))
    .flatten()
    .value();

  const presets = extendsArray
    .filter((preset) => !['eslint:recommended', 'eslint:all'].includes(preset))
    .map((preset) => resolvePresetPackage(preset, rootDir));

  // prettier/recommended extends eslint-config-prettier
  // https://github.com/prettier/eslint-plugin-prettier#recommended-configuration
  if (extendsArray.includes('plugin:prettier/recommended')) {
    presets.push('eslint-config-prettier');
  }

  const presetPackages = presets
    .filter((preset) => !path.isAbsolute(preset))
    .map(requirePackageName);

  const presetDeps = lodash(presets)
    .map((preset) => requireConfig(preset, rootDir))
    .map(([presetConfig, deps]) => checkConfig(presetConfig, rootDir, deps))
    .flatten()
    .value();

  const result = lodash
    .union(parser, plugins, presetPackages, presetDeps)
    .filter((dep) => !includedDeps.includes(dep));

  configs.forEach((value) => {
    if (value.settings) {
      Object.keys(value.settings).forEach((key) => {
        if (key !== 'import/resolver') {
          return;
        }
        Object.keys(value.settings[key]).forEach((resolverName) => {
          // node and webpack resolvers are included in `eslint-plugin-import`
          if (!['node', 'webpack'].includes(resolverName)) {
            result.push(`eslint-import-resolver-${resolverName}`);
          }
        });
      });
    }
  });

  return result;
}

const configNameRegex = /^\.eslintrc(\.(json|js|yml|yaml))?$/;

export default async function parseESLint(filename, deps, rootDir) {
  const config = await loadConfig('eslint', configNameRegex, filename, rootDir);

  if (config) {
    return checkConfig(config, rootDir);
  }

  const packageJsonPath = path.resolve(rootDir, 'package.json');
  const resolvedFilePath = path.resolve(rootDir, filename);

  if (resolvedFilePath === packageJsonPath) {
    const content = await getContent(filename);
    const parsed = JSON.parse(content);
    if (parsed.eslintConfig) {
      return checkConfig(parsed.eslintConfig, rootDir);
    }
  }

  return [];
}
<|endoftext|>


<commit_before>import { definePropertyRO, definePropertyRW, noe, isValidNum } from './utils';
import Position from './position';
import Token from './token';
import TokenStream from './token-stream';
import { isValidResult, convertToTokenParser, createTokenParser, isSuccessful, loop, REGEXP, EQ, ALIAS } from './parser-engine';

export const REPEAT = createTokenParser(function(_getter, _min, _max) {
  var getter = convertToTokenParser(_getter),
      min = (_min === undefined) ? 0 : _min,
      max = (_max === undefined) ? Infinity : _max;

  if (arguments.length === 2)
    max = min;

  return loop.call(this, (index, done, previousValue, values) => {
    if (index > 0 && !isValidResult(previousValue)) {
      if ((index - 1) >= min)
        return done(values.slice(0, -1));

      return done(null);
    }

    //console.log('LOOPING!!', index);
    if (index >= max)
      return done();

    return getter.call(this);
  });
}, function(result) {
  if (!isValidResult(result))
    return;

  return new Token({
    type: 'REPEAT',
    source: this,
    position: result[result.length - 1].position,
    value: result.map((t) => t.value).join(''),
    rawValue: result
  });
});

export const NOT = createTokenParser(function(_parser) {
  var parser = convertToTokenParser(_parser);
  return parser.call(this);
}, function(result) {
  if (!result || result.success === true)
    return;

  return new Token({
    type: 'NOT',
    source: result.source,
    position: result.position,
    value: result.value,
    rawValue: result.rawValue,
    success: true
  });
});

export const OR = createTokenParser(function(...parsers) {
  return loop.call(this, (index, done, previousValue) => {
    if (index > 0 && isValidResult(previousValue))
      return done(previousValue);

    if (index >= parsers.length)
      return done(null);

    return convertToTokenParser(parsers[index]).call(this);
  });
});

export const AND = createTokenParser(function(...parsers) {
  var results = [];

  for (var i = 0, il = parsers.length; i < il; i++) {
    var parser = convertToTokenParser(parsers[i]),
        value = parser.call(this);

    if (!isValidResult(value))
      return;

    results.push(value);
  }

  return results;
}, function(result) {
  if (!isValidResult(result))
    return;

  return new Token({
    type: 'AND',
    source: this,
    position: result[result.length - 1].position,
    value: result.map((t) => t.value).join(''),
    rawValue: result
  });
});

export const BODY = createTokenParser(function(boundaryChar, name) {
  if (!boundaryChar || boundaryChar.length !== 1)
    throw new Error('Boundary character must be exactly one character');

  if (this.eof())
    return;

  var startPos = this.offset,
      c = this.get();

  if (c !== boundaryChar)
    return;

  while (!this.eof()) {
    var c = this.get();
    if (c === '\\') {
      this.get();
      continue;
    }

    if (c === boundaryChar)
      break;
  }

  if (c !== boundaryChar)
    this.raise('Unexpected end of input');

  return this.get(new Position(startPos, this.offset)).toString();
}, function(result, c, name) {
  if (!isValidResult(result))
    return;

  return new Token({
    type: name || 'BODY',
    source: this,
    position: result.length,
    value: result.substring(1, result.length - 1),
    rawValue: result,
    success: true
  });
});

class Tokenizer {
  constructor(token, _opts) {
    var opts = _opts || {};

    this.token = token;
    this.options = opts;
  }

  parse(input, cb) {
    var src = new TokenStream(input),
        ret = this.token.call(src);

    if (ret instanceof Promise)
      ret.then((result) => cb.call(this, null, result), (err) => cb.call(err, null));
    else
      cb.call(this, null, ret);
  }
}

const TEST = createTokenParser(function() {
  var startPos = this.offset;
  return new Promise((resolve) => {
    setTimeout(() => {
      var pos = new Position(startPos, startPos + 5),
          str = this.get(pos).toString();

      resolve(new Token({
        type: 'TEST',
        source: this,
        position: pos,
        value: str
      }));
    }, 15);
  });
});

const MY_TOKEN = ALIAS(OR(/\w+/), 'MY_TOKEN');

//BODY('"', "STRING_DQ"), BODY("'", "STRING_SQ")

var tokenizer = new Tokenizer(REPEAT(OR(MY_TOKEN, TEST)));
tokenizer.parse('This stuff derp hello "this is a \\" DQ string" stuff and \'here we see a single quoted string', function(err, result) {
  console.log('FINAL RESULT: ', result);
});
<commit_msg>Updates<commit_after>import { definePropertyRO, definePropertyRW, noe, isValidNum } from './utils';
import Position from './position';
import Token from './token';
import TokenStream from './token-stream';
import { isValidResult, convertToTokenParser, createTokenParser, isSuccessful, loop, REGEXP, EQ, ALIAS } from './parser-engine';

export const REPEAT = createTokenParser(function(_getter, _min, _max) {
  var getter = convertToTokenParser(_getter),
      min = (_min === undefined) ? 0 : _min,
      max = (_max === undefined) ? Infinity : _max;

  if (arguments.length === 2)
    max = min;

  return loop.call(this, (index, done, previousValue, values) => {
    if (index > 0 && !isValidResult(previousValue)) {
      if ((index - 1) >= min)
        return done(values.slice(0, -1));

      return done(null);
    }

    //console.log('LOOPING!!', index);
    if (index >= max)
      return done();

    return getter.call(this);
  });
}, function(result) {
  if (!isValidResult(result))
    return;

  return new Token({
    type: 'REPEAT',
    source: this,
    position: result[result.length - 1].position,
    value: result.map((t) => t.value).join(''),
    rawValue: result
  });
});

export const NOT = createTokenParser(function(_parser) {
  var parser = convertToTokenParser(_parser);
  return parser.call(this);
}, function(result) {
  if (!result || result.success === true)
    return;

  return new Token({
    type: 'NOT',
    source: result.source,
    position: result.position,
    value: result.value,
    rawValue: result.rawValue,
    success: true
  });
});

export const OR = createTokenParser(function(...parsers) {
  return loop.call(this, (index, done, previousValue) => {
    if (index > 0 && isValidResult(previousValue))
      return done(previousValue);

    if (index >= parsers.length)
      return done(null);

    return convertToTokenParser(parsers[index]).call(this);
  });
});

export const AND = createTokenParser(function(...parsers) {
  var results = [];

  return loop.call(this, (index, done, previousValue, values) => {
    if (index > 0 && !isValidResult(previousValue))
      return done(null);

    if (index >= parsers.length)
      return done();

    return convertToTokenParser(parsers[index]).call(this);
  });
}, function(result) {
  if (!isValidResult(result))
    return;

  return new Token({
    type: 'AND',
    source: this,
    position: result[result.length - 1].position,
    value: result.map((t) => t.value).join(''),
    rawValue: result
  });
});

export const BODY = createTokenParser(function(boundaryChar, name) {
  if (!boundaryChar || boundaryChar.length !== 1)
    throw new Error('Boundary character must be exactly one character');

  if (this.eof())
    return;

  var startPos = this.offset,
      c = this.get();

  if (c !== boundaryChar)
    return;

  while (!this.eof()) {
    var c = this.get();
    if (c === '\\') {
      this.get();
      continue;
    }

    if (c === boundaryChar)
      break;
  }

  if (c !== boundaryChar)
    this.raise('Unexpected end of input');

  return this.get(new Position(startPos, this.offset)).toString();
}, function(result, c, name) {
  if (!isValidResult(result))
    return;

  return new Token({
    type: name || 'BODY',
    source: this,
    position: result.length,
    value: result.substring(1, result.length - 1),
    rawValue: result,
    success: true
  });
});

class Tokenizer {
  constructor(token, _opts) {
    var opts = _opts || {};

    this.token = token;
    this.options = opts;
  }

  parse(input, cb) {
    var src = new TokenStream(input),
        ret = this.token.call(src);

    if (ret instanceof Promise)
      ret.then((result) => cb.call(this, null, result), (err) => cb.call(err, null));
    else
      cb.call(this, null, ret);
  }
}

const TEST = createTokenParser(function() {
  var startPos = this.offset;
  return new Promise((resolve) => {
    setTimeout(() => {
      var pos = new Position(startPos, startPos + 5),
          str = this.get(pos).toString();

      resolve(new Token({
        type: 'TEST',
        source: this,
        position: pos,
        value: str
      }));
    }, 15);
  });
});

const MY_TOKEN = ALIAS(OR(/\w+/), 'MY_TOKEN');

//BODY('"', "STRING_DQ"), BODY("'", "STRING_SQ")

var tokenizer = new Tokenizer(AND(/\w+/, /\s+/, /\w+/, TEST));
tokenizer.parse('This stuff derp hello "this is a \\" DQ string" stuff and \'here we see a single quoted string', function(err, result) {
  console.log('FINAL RESULT: ', result);
});
<|endoftext|>


<commit_before>import Phaser from 'phaser'

export default class extends Phaser.Sprite {
  constructor ({ game, x, y, asset, weaponType, weaponLevel, firingRateLevel }) {
    super(game, x, y, asset, weaponType, weaponLevel, firingRateLevel)
    this.anchor.setTo(0.5, 0.5)
    this.game.physics.enable(this, Phaser.Physics.ARCADE);
    this.bulletTime = 0;
    this.weapon = {
      type: 'bullet',
      level: weaponLevel
    };
    this.firingRateLevel = (firingRateLevel) ? firingRateLevel : 0;
    this.firingRate = 400 - (this.firingRateLevel * 20);
  }

  update () {
    if (this.alive) {
        if (this.game.lasers) this.game.lasers.align
        //  Reset the player, then check for movement keys
        this.body.velocity.setTo(0, 0);

        if (this.game.cursors.left.isDown) {
            // Limit left side to bounds
            if (this.body.position.x < this.game.world.bounds.x) {
                this.body.velocity.x = 0
            } else {
                this.body.velocity.x = -200;
            }
        } else if (this.game.cursors.right.isDown) {
            // Limit right side to bounds
            if (this.body.position.x > this.game.world.bounds.width - this.body.width) {
                this.body.velocity.x = 0
            } else {
                this.body.velocity.x = 200;
            }
        }

        if (this.game.cursors.up.isDown) {
          // Limit top side to bounds
          if (this.body.position.y < this.game.world.bounds.y) {
              this.body.velocity.y = 0
          } else {
              this.body.velocity.y = -200;
          }
        } else if (this.game.cursors.down.isDown) {
          // Limit bottom side to bounds
          if (this.body.position.y > this.game.world.bounds.height - this.body.height) {
              this.body.velocity.y = 0
          } else {
              this.body.velocity.y = 200;
          }
        }

        //  Firing?
        if (this.game.fireButton.isDown) {
            // check weapon type
            if (this.weapon.type === 'bullet') {
              this.fireBullet();
            } else if (this.weapon.type === 'laser') {
              this.fireLaser();
            }

        }

        //  Run collision
        this.game.physics.arcade.overlap(this.game.alienBullets, this, this.alienBulletHitsPlayer, null, this);
    }
  }

  fireLaser() {
      console.log('laser fired')
      if (this.game.time.now > this.bulletTime) {
        let laser = this.game.lasers.getTop();
        laser.reset(this.x, this.y);
        laser.body.velocity.y = -400;
        laser.sendToBack();
        this.bulletTime = this.game.time.now + 5

      }

  }

  fireBullet() {

        //  To avoid them being allowed to fire too fast we set a time limit
    if (this.game.time.now > this.bulletTime) {
        //  Grab the first bullet we can from the pool
        if (this.weapon.level === 1) {
          this.bullet = this.game.bullets.getFirstExists(false);

          if (this.bullet) {
            //  And fire it
            this.bullet.reset(this.x, this.y + 10);
            this.bullet.body.velocity.y = -400;
            this.bulletTime = this.game.time.now + this.firingRate;
          }
        }

        // Level 2 bullets

        if (this.weapon.level === 2) {
          this.bullets = [];
          for (let i = 0; i < this.weapon.level; i++) {
            this.bullets.push(this.game.bullets.getTop());
            this.game.bullets.getTop().sendToBack()
          }

          if (this.bullets.length === 2) {
            //  Fire two bullets
            this.bullets[0].reset(this.x - 8, this.y + 10);
            this.bullets[0].body.velocity.y = -400;
            this.bullets[1].reset(this.x + 8, this.y + 10);
            this.bullets[1].body.velocity.y = -400;
            this.bulletTime = this.game.time.now + this.firingRate;
          }
        }

        // Level 3 bullets
        if (this.weapon.level === 3) {
          this.bullets = [];
          for (let i = 0; i < this.weapon.level; i++) {
            this.bullets.push(this.game.bullets.getTop());
            this.game.bullets.getTop().sendToBack()
          }

          if (this.bullets.length === 3) {
            //  Fire three bullets
            this.bullets[0].reset(this.x - 10, this.y + 10);
            this.bullets[0].body.velocity.y = -400;
            this.bullets[1].reset(this.x, this.y + 10);
            this.bullets[1].body.velocity.y = -400;
            this.bullets[2].reset(this.x + 10, this.y + 10);
            this.bullets[2].body.velocity.y = -400;
            this.bulletTime = this.game.time.now + this.firingRate;
          }
        }

        // Level 4 bullets
        if (this.weapon.level === 4) {
          this.bullets = [];
          for (let i = 0; i < this.weapon.level; i++) {
            this.bullets.push(this.game.bullets.getTop());
            this.game.bullets.getTop().sendToBack()
          }

          if (this.bullets.length === 4) {
            //  Fire four bullets
            this.bullets[0].reset(this.x - 10, this.y + 15);
            this.bullets[0].body.velocity.y = -350;
            this.bullets[0].body.velocity.x = -50;
            this.bullets[1].reset(this.x - 5, this.y + 15);
            this.bullets[1].body.velocity.y = -400;
            this.bullets[2].reset(this.x + 5, this.y + 15);
            this.bullets[2].body.velocity.y = -400;
            this.bullets[3].reset(this.x + 10, this.y + 15);
            this.bullets[3].body.velocity.y = -350;
            this.bullets[3].body.velocity.x = 50;
            this.bulletTime = this.game.time.now + this.firingRate;
          }
        }

    }

  }

  alienBulletHitsPlayer (player, bullet) {
    // if alien hits player kill player and bullet
    bullet.kill();
    player.kill();
  }
}
<commit_msg>adjust level 4 bullet position<commit_after>import Phaser from 'phaser'

export default class extends Phaser.Sprite {
  constructor ({ game, x, y, asset, weaponType, weaponLevel, firingRateLevel }) {
    super(game, x, y, asset, weaponType, weaponLevel, firingRateLevel)
    this.anchor.setTo(0.5, 0.5)
    this.game.physics.enable(this, Phaser.Physics.ARCADE);
    this.bulletTime = 0;
    this.weapon = {
      type: 'bullet',
      level: weaponLevel
    };
    this.firingRateLevel = (firingRateLevel) ? firingRateLevel : 0;
    this.firingRate = 400 - (this.firingRateLevel * 20);
  }

  update () {
    if (this.alive) {
        if (this.game.lasers) this.game.lasers.align
        //  Reset the player, then check for movement keys
        this.body.velocity.setTo(0, 0);

        if (this.game.cursors.left.isDown) {
            // Limit left side to bounds
            if (this.body.position.x < this.game.world.bounds.x) {
                this.body.velocity.x = 0
            } else {
                this.body.velocity.x = -200;
            }
        } else if (this.game.cursors.right.isDown) {
            // Limit right side to bounds
            if (this.body.position.x > this.game.world.bounds.width - this.body.width) {
                this.body.velocity.x = 0
            } else {
                this.body.velocity.x = 200;
            }
        }

        if (this.game.cursors.up.isDown) {
          // Limit top side to bounds
          if (this.body.position.y < this.game.world.bounds.y) {
              this.body.velocity.y = 0
          } else {
              this.body.velocity.y = -200;
          }
        } else if (this.game.cursors.down.isDown) {
          // Limit bottom side to bounds
          if (this.body.position.y > this.game.world.bounds.height - this.body.height) {
              this.body.velocity.y = 0
          } else {
              this.body.velocity.y = 200;
          }
        }

        //  Firing?
        if (this.game.fireButton.isDown) {
            // check weapon type
            if (this.weapon.type === 'bullet') {
              this.fireBullet();
            } else if (this.weapon.type === 'laser') {
              this.fireLaser();
            }

        }

        //  Run collision
        this.game.physics.arcade.overlap(this.game.alienBullets, this, this.alienBulletHitsPlayer, null, this);
    }
  }

  fireLaser() {
      console.log('laser fired')
      if (this.game.time.now > this.bulletTime) {
        let laser = this.game.lasers.getTop();
        laser.reset(this.x, this.y);
        laser.body.velocity.y = -400;
        laser.sendToBack();
        this.bulletTime = this.game.time.now + 5

      }

  }

  fireBullet() {

        //  To avoid them being allowed to fire too fast we set a time limit
    if (this.game.time.now > this.bulletTime) {
        //  Grab the first bullet we can from the pool
        if (this.weapon.level === 1) {
          this.bullet = this.game.bullets.getFirstExists(false);

          if (this.bullet) {
            //  And fire it
            this.bullet.reset(this.x, this.y + 10);
            this.bullet.body.velocity.y = -400;
            this.bulletTime = this.game.time.now + this.firingRate;
          }
        }

        // Level 2 bullets

        if (this.weapon.level === 2) {
          this.bullets = [];
          for (let i = 0; i < this.weapon.level; i++) {
            this.bullets.push(this.game.bullets.getTop());
            this.game.bullets.getTop().sendToBack()
          }

          if (this.bullets.length === 2) {
            //  Fire two bullets
            this.bullets[0].reset(this.x - 8, this.y + 10);
            this.bullets[0].body.velocity.y = -400;
            this.bullets[1].reset(this.x + 8, this.y + 10);
            this.bullets[1].body.velocity.y = -400;
            this.bulletTime = this.game.time.now + this.firingRate;
          }
        }

        // Level 3 bullets
        if (this.weapon.level === 3) {
          this.bullets = [];
          for (let i = 0; i < this.weapon.level; i++) {
            this.bullets.push(this.game.bullets.getTop());
            this.game.bullets.getTop().sendToBack()
          }

          if (this.bullets.length === 3) {
            //  Fire three bullets
            this.bullets[0].reset(this.x - 10, this.y + 10);
            this.bullets[0].body.velocity.y = -400;
            this.bullets[1].reset(this.x, this.y + 10);
            this.bullets[1].body.velocity.y = -400;
            this.bullets[2].reset(this.x + 10, this.y + 10);
            this.bullets[2].body.velocity.y = -400;
            this.bulletTime = this.game.time.now + this.firingRate;
          }
        }

        // Level 4 bullets
        if (this.weapon.level === 4) {
          this.bullets = [];
          for (let i = 0; i < this.weapon.level; i++) {
            this.bullets.push(this.game.bullets.getTop());
            this.game.bullets.getTop().sendToBack()
          }

          if (this.bullets.length === 4) {
            //  Fire four bullets
            this.bullets[0].reset(this.x - 10, this.y - 8);
            this.bullets[0].body.velocity.y = -350;
            this.bullets[0].body.velocity.x = -50;
            this.bullets[1].reset(this.x - 5, this.y - 8);
            this.bullets[1].body.velocity.y = -400;
            this.bullets[2].reset(this.x + 5, this.y - 8);
            this.bullets[2].body.velocity.y = -400;
            this.bullets[3].reset(this.x + 10, this.y - 8);
            this.bullets[3].body.velocity.y = -350;
            this.bullets[3].body.velocity.x = 50;
            this.bulletTime = this.game.time.now + this.firingRate;
          }
        }

    }

  }

  alienBulletHitsPlayer (player, bullet) {
    // if alien hits player kill player and bullet
    bullet.kill();
    player.kill();
  }
}
<|endoftext|>