diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..6a75ac8 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,6 @@ +{ + "extends": "standard", + "globals": { + "Zone": true + } +} diff --git a/.gitignore b/.gitignore index a80268c..798c79f 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ node_modules # Optional REPL history .node_repl_history queue.js + +# VS Code stuff related +.vscode diff --git a/.vscode/launch.json b/.vscode/launch.json index 5e0c1c5..a42481e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,12 +4,26 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - + { "type": "node", "env": {"RUN_MODE": "1"}, "request": "launch", - "name": "Launch Program", + "name": "Launch Real Life", + "program": "${workspaceFolder}/server.js" + }, + { + "type": "node", + "env": {"RUN_MODE": "3"}, + "request": "launch", + "name": "Launch Simulated", + "program": "${workspaceFolder}/server.js" + }, + { + "type": "node", + "env": {"RUN_MODE": "4"}, + "request": "launch", + "name": "Launch Passive", "program": "${workspaceFolder}/server.js" } ] diff --git a/Intention/LineIntention.js b/Intention/LineIntention.js index cd3138d..4d808b5 100644 --- a/Intention/LineIntention.js +++ b/Intention/LineIntention.js @@ -1,45 +1,30 @@ -/****************************************** - * Project Neon 2017 * - ****************************************** - -To see more of the documentation visit: - -https://github.com/Project-Neon/NoPlan/blob/master/Intention/README.md - -*/ const util = require('./util') const Intention = require('./') const assert = require('assert') const Vector = require('../lib/Vector') -module.exports = class LineIntention extends Intention{ - constructor(name, params) { +module.exports = class LineIntention extends Intention { + constructor (name, params) { super(name, params) - // Asserting that the parameters exist assert(params) this.params = params - // Target has to exist assert.notEqual(this.params.target, null) this.target = this.params.target - // Theta has to exist assert.notEqual(this.params.theta, null) this.theta = this.params.theta - // Decay has to exist assert.notEqual(this.params.decay, null) this.decay = this.params.decay - - // Linesize has to exist + assert.notEqual(this.params.lineSize, null) - this.lineSize = this.params.lineSize - - // LineDist has to exist + this.lineSize = this.params.lineSize + assert.notEqual(this.params.lineDist, null) this.lineDist = this.params.lineDist - + this.lineDistMax = this.params.lineDistMax || false // Use this to make the line work on only one size @@ -50,68 +35,43 @@ module.exports = class LineIntention extends Intention{ this.multiplier = this.params.multiplier || 1 } - // getIntentionInfo() { - // return { - // 'type': LineIntention.name, - // 'name': this.name, - // 'params': JSON.parse(JSON.stringify(util.mapDict(this.params, x => util.callOrReturn(x)))) - // } - // } - - compute({x, y, theta}) { + compute ({x, y}) { // Instanciate target values let targetLine = util.callOrReturn(this.target) let targetTheta = util.callOrReturn(this.theta) let lineDistMax = util.callOrReturn(this.lineDistMax) let multiplier = util.callOrReturn(this.multiplier) - + // Create vectors let toLine = Vector.sub({x, y}, targetLine) - let toLineScalar = Vector.size(toLine) let toLineWithTheta = Vector.rotate(toLine, -targetTheta) - // Position at line: toLineWithTheta.y - // Distance from line: toLineWithTheta.x - // Output 0 if outside line segment - if (this.lineSize && Math.abs(toLineWithTheta.x) > this.lineSize) { - // console.log('Outside line segment') - return {vx: 0, vy: 0, vtheta: 0} - } + if (this.lineSize && Math.abs(toLineWithTheta.x) > this.lineSize) return {vx: 0, vy: 0, vtheta: 0} // Output 0 if on the other side of the line and single side is active - if (this.lineSizeSingleSide && toLineWithTheta.x < 0) { - // console.log('On other side of line size') - return {vx: 0, vy: 0, vtheta: 0} - } + if (this.lineSizeSingleSide && toLineWithTheta.x < 0) return {vx: 0, vy: 0, vtheta: 0} // Output 0 if outside maximum distance - if (lineDistMax && Math.abs(toLineWithTheta.y) > lineDistMax) { - // console.log('Outside maximum distance') - return {vx: 0, vy: 0, vtheta: 0} - } + if (lineDistMax && Math.abs(toLineWithTheta.y) > lineDistMax) return {vx: 0, vy: 0, vtheta: 0} // Output 0 if on the other side of the line and single side is active - if (this.lineDistSingleSide && toLineWithTheta.y < 0) { - // console.log('on other side of line dist') - return {vx: 0, vy: 0, vtheta: 0} - } - + if (this.lineDistSingleSide && toLineWithTheta.y < 0) return {vx: 0, vy: 0, vtheta: 0} + // Normalizing vector let toLineNorm = Vector.norm(Vector.rotate({y: toLineWithTheta.y, x: 0}, targetTheta)) // Normalized Scalar let toLineScalarNorm = Math.max(0, Math.min(1, (Math.abs(toLineWithTheta.y) / this.lineDist))) - //console.log(toLineNorm, toLineScalarNorm, ) // Apply decay function to normalized distance from the beginning to the end of the field let force = util.applyReflectedDecay(this.decay, toLineScalarNorm) return { - // Returning result vector times the multiplier as output. + // Returning result vector times the multiplier as output. vx: toLineNorm.x * force * multiplier, vy: toLineNorm.y * force * multiplier, vtheta: 0 } } -} \ No newline at end of file +} diff --git a/Intention/LookAtIntention.js b/Intention/LookAtIntention.js index 7db1779..3edef81 100644 --- a/Intention/LookAtIntention.js +++ b/Intention/LookAtIntention.js @@ -1,47 +1,37 @@ -/****************************************** - * Project Neon 2017 * - ****************************************** - -To see more of the documentation visit: - -https://github.com/Project-Neon/NoPlan/blob/master/Intention/README.md - -*/ const util = require('./util') const Intention = require('./') const assert = require('assert') const Vector = require('../lib/Vector') -module.exports = class LookAtIntention extends Intention{ - constructor(name, params) { +module.exports = class LookAtIntention extends Intention { + constructor (name, params) { super(name, params) - - // Asserting that the params exist + // Asserting that the params exist assert(params) this.params = params // Either target or theta has to be declared assert.notEqual(this.params.theta || this.params.target, null) - this.theta = this.params.theta - this.target = this.params.target - // Decay has to be declared assert.notEqual(this.params.decay, null) + this.decay = this.params.decay + this.theta = this.params.theta + this.target = this.params.target // If multiplier is not declared it is 1 this.multiplier = this.params.multiplier || 1 } - getIntentionInfo() { + getIntentionInfo () { return { 'type': LookAtIntention.name, 'name': this.name, - 'params': JSON.parse(JSON.stringify(util.mapDict(this.params, x => util.callOrReturn(x))))// util.mapDict(this.params , function(v, k, o) { return util.callOrReturn(v)}) + 'params': JSON.parse(JSON.stringify(util.mapDict(this.params, x => util.callOrReturn(x)))) } } - compute({x, y, theta}) { + compute ({x, y, theta}) { // Instaciate theta values let absRobotAngle = theta let absTargetAngle = util.callOrReturn(this.theta) @@ -49,9 +39,9 @@ module.exports = class LookAtIntention extends Intention{ // If no theta was used but target was: if (absTargetAngle == null) { let targetLookAt = util.callOrReturn(this.target) - absTargetAngle = Vector.angle(Vector.sub(targetLookAt, {x,y})) + absTargetAngle = Vector.angle(Vector.sub(targetLookAt, {x, y})) } - + // The difference between angles. let deltaAngle = Vector.normalRelativeAngle(absRobotAngle - absTargetAngle) @@ -73,4 +63,4 @@ module.exports = class LookAtIntention extends Intention{ vtheta: vtheta * this.multiplier } } -} \ No newline at end of file +} diff --git a/Intention/OrbitalIntention.js b/Intention/OrbitalIntention.js index cd2d04c..56c0873 100644 --- a/Intention/OrbitalIntention.js +++ b/Intention/OrbitalIntention.js @@ -1,19 +1,10 @@ -/****************************************** - * Project Neon 2017 * - ****************************************** - -To see more of the documentation visit: - -https://github.com/Project-Neon/NoPlan/blob/master/Intention/README.md - -*/ const util = require('./util') const Intention = require('./') const assert = require('assert') const Vector = require('../lib/Vector') -module.exports = class OrbitalIntention extends Intention{ - constructor(name, params) { +module.exports = class OrbitalIntention extends Intention { + constructor (name, params) { super(name, params) // Asserting that the parameters exist @@ -27,35 +18,48 @@ module.exports = class OrbitalIntention extends Intention{ assert.notEqual(this.params.clockwise, null) this.clockwise = this.params.clockwise + assert.notEqual(this.params.decay, null) + this.decay = this.params.decay + // Radius of the orbitation movement assert.notEqual(this.params.radius, null) this.radius = this.params.radius + // Is there a maximum radius? + this.radiusMax = this.params.radiusMax || false + // If multiplier is not declared it is 1 this.multiplier = this.params.multiplier || 1 } - compute({x, y, theta}) { + compute ({x, y}) { // Instanciate target values let target = util.callOrReturn(this.target) - let multiplier = util.callOrReturn(this.multiplier) let clockwise = util.callOrReturn(this.clockwise) - - let angleToTarget = -Math.atan2(target.y - y, x - target.x); - let K = 100 + let angleToTarget = Math.atan2(target.y - y, target.x - x) + let K = 1/200 let distanceBetweenTarget = Vector.distBetween({x, y}, target) let endAngle + let radiusMax = this.radiusMax + + // Out of max radius ? output is 0 + if (radiusMax && distanceBetweenTarget > radiusMax) return {vx: 0, vy: 0, vtheta: 0} + if (distanceBetweenTarget > this.radius) { - endAngle = angleToTarget + clockwise * Math.PI/2 * (2 + (this.radius + K)/(distanceBetweenTarget + K)) + endAngle = angleToTarget + clockwise * (Math.PI / 2) * (2 - ((this.radius + K) / (distanceBetweenTarget + K))) } else { - endAngle = angleToTarget + clockwise * Math.PI/2 * Math.sqrt(distanceBetweenTarget/this.radius) + endAngle = angleToTarget + clockwise * (Math.PI / 2) * Math.sqrt(distanceBetweenTarget / this.radius) } + + let toTargetScalarNorm = Math.max(0, Math.min(1, distanceBetweenTarget / (this.radius))) let finalVector = Vector.norm(Vector.fromTheta(endAngle)) + let force = util.applyReflectedDecay(this.decay, toTargetScalarNorm) + return { // Returning result vector times the multiplier as output. - vx: finalVector.x * this.multiplier, - vy: finalVector.y * this.multiplier, + vx: finalVector.x * force * this.multiplier, + vy: finalVector.y * force * this.multiplier, vtheta: 0 } } diff --git a/Intention/PointIntention.js b/Intention/PointIntention.js index cf1a057..acd3415 100644 --- a/Intention/PointIntention.js +++ b/Intention/PointIntention.js @@ -1,19 +1,10 @@ -/****************************************** - * Project Neon 2017 * - ****************************************** - -To see more of the documentation visit: - -https://github.com/Project-Neon/NoPlan/blob/master/Intention/README.md - -*/ const util = require('./util') const Intention = require('./') const assert = require('assert') const Vector = require('../lib/Vector') -module.exports = class PointIntention extends Intention{ - constructor(name, params) { +module.exports = class PointIntention extends Intention { + constructor (name, params) { super(name, params) // Asserting that the parameters exist @@ -29,7 +20,7 @@ module.exports = class PointIntention extends Intention{ this.decay = this.params.decay // Radius has to be exist - assert.notEqual(this.params.radius , null) + assert.notEqual(this.params.radius, null) this.radius = this.params.radius || this.radiusMax // Is there a maximum radius? @@ -39,7 +30,7 @@ module.exports = class PointIntention extends Intention{ this.multiplier = this.params.multiplier || 1 } - getIntentionInfo() { + getIntentionInfo () { return { 'type': PointIntention.name, 'name': this.name, @@ -47,7 +38,7 @@ module.exports = class PointIntention extends Intention{ } } - compute({x, y, theta}) { + compute ({x, y, theta}) { // Instaciate target values let targetGoto = util.callOrReturn(this.target) let radiusMax = util.callOrReturn(this.radiusMax) @@ -57,22 +48,18 @@ module.exports = class PointIntention extends Intention{ let toTarget = Vector.sub(targetGoto, {x, y}) let toTargetScalar = Vector.size(toTarget) - // Out of max radius ? output is 0 - if (radiusMax && toTargetScalar > radiusMax) { - // console.log('Outside radius') - return {vx: 0, vy: 0, vtheta: 0} - } + // Out of max radius ? output is 0 + if (radiusMax && toTargetScalar > radiusMax) return {vx: 0, vy: 0, vtheta: 0} // Normalized Vector let toTargetNorm = Vector.norm(toTarget) - + // Normalized Scalar let toTargetScalarNorm = Math.max(0, Math.min(1, toTargetScalar / (this.radius))) // Apply decay to normalized scalar distance let force = util.applyReflectedDecay(this.decay, toTargetScalarNorm) - // console.log("Name: ",this.name, force) return { // Returning result vector times the multiplier as output vx: -1 * toTargetNorm.x * force * multiplier, @@ -80,4 +67,4 @@ module.exports = class PointIntention extends Intention{ vtheta: 0 } } -} \ No newline at end of file +} diff --git a/Intention/index.js b/Intention/index.js index 2fd1eea..cf122af 100644 --- a/Intention/index.js +++ b/Intention/index.js @@ -6,9 +6,8 @@ const STABILIZED_MIN_LINEAR = 30 const STABILIZED_MIN_ANGULAR = 0.5 module.exports = class Intention { - constructor(name, params) { + constructor (name, params) { params = params || {} - this.name = name this.time = 0 this.weight = (params.weight == null ? 1 : params.weight) @@ -16,77 +15,61 @@ module.exports = class Intention { this.intentions = [] } - addIntetion(intention) { - // Avoid same object twice in list - if (this.intentions.includes(intention)) - return; - + addIntetion (intention) { + if (this.intentions.includes(intention)) return this.intentions.push(intention) - return intention } - getIntentionInfo() { + getIntentionInfo () { return this.intentions.map(x => x.getIntentionInfo()) } - isStabilized() { - // Is Last compute too old? - if (Date.now() > this.time + FRESH_OUTPUT_TIME) return false; - // Has it been computed yet? - if (!this.output) return false; - // Is it active? - if (!this.active) return false; - - // Is it stabilized with outputs? - if (Math.abs(this.output.vx) > STABILIZED_MIN_LINEAR) return false; - if (Math.abs(this.output.vy) > STABILIZED_MIN_LINEAR) return false; - if (Math.abs(this.output.vtheta) > STABILIZED_MIN_ANGULAR) return false; - + isStabilized () { + if (Date.now() > this.time + FRESH_OUTPUT_TIME) return false + if (!this.output) return false + if (!this.active) return false + + if (Math.abs(this.output.vx) > STABILIZED_MIN_LINEAR) return false + if (Math.abs(this.output.vy) > STABILIZED_MIN_LINEAR) return false + if (Math.abs(this.output.vtheta) > STABILIZED_MIN_ANGULAR) return false + return true } - get active() { + get active () { return this.weight > MIN_WEIGHT_ACTIVE } - compute(input) { + compute (input) { let outputSum = {vx: 0, vy: 0, vtheta: 0} let outputSumWeight = 0 for (let intention of this.intentions) { - if (!intention.active) - continue + if (!intention.active) continue let weight = util.callOrReturn(intention.weight) - let output = intention.compute(input) - // Save inside intention the lastOutput intention.output = output - if (!output) { console.log('Fudeo o role:', intention.name, 'com: ', output) - continue; + continue } outputSumWeight += weight - for (let key in outputSum) { - // console.log(`int: ${intention.name} weight: ${intention.weight} key,val: ${key},${output[key]}`) outputSum[key] += output[key] * Math.min(1, Math.max(0, weight)) } } - // Make sure weights are ok, or return nothing if (outputSumWeight <= MIN_WEIGHT_ACTIVE) { outputSum = {vx: 0, vy: 0, vtheta: 0} } - // Save current time and summed output this.time = Date.now() this.output = outputSum return outputSum } -} \ No newline at end of file +} diff --git a/Intention/util.js b/Intention/util.js index 7afac14..ab28cbf 100644 --- a/Intention/util.js +++ b/Intention/util.js @@ -1,22 +1,19 @@ // Checks if the object is a function or a value -exports.callOrReturn = function callOrReturn(value){ - return (typeof value === "function") ? value() : value +exports.callOrReturn = function callOrReturn (value) { + return (typeof value === 'function') ? value() : value } // Applies the decay from -1 to 1 -exports.applyReflectedDecay = function applyReflectedDecay(decayFn, value) { - if (!decayFn) return value; - +exports.applyReflectedDecay = function applyReflectedDecay (decayFn, value) { + if (!decayFn) return value let out = decayFn(Math.abs(value)) - // Re-reverse out function based on initial value return (value < 0 ? -out : out) } - -exports.mapDict = function mapDict(o, f, ctx) { - ctx = ctx || this; - var result = {}; - Object.keys(o).forEach(function(k) { - result[k] = f.call(ctx, o[k], k, o); - }); - return result; -} \ No newline at end of file +exports.mapDict = function mapDict (o, f, ctx) { + ctx = ctx || this + var result = {} + Object.keys(o).forEach(function (k) { + result[k] = f.call(ctx, o[k], k, o) + }) + return result +} diff --git a/README.md b/README.md index ada8bb8..4865fca 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ NoPlan is the software used to guide our Very Small Size Soccer Robots. -With NoPlan, we aim to create a project that can be developed by as many team members as possible at the same time. To improve productivity, we follow part of the Git - flow cheat sheet. We use Master as our "competition" code and develop as our main branch. Also, we created "legacy" as old code of "LARC-2017" branch, a safe point to return. +With NoPlan, we aim to create a project that can be developed by as many team members as possible at the same time. To improve productivity, we follow part of the [Gitflow cheat sheet](https://danielkummer.github.io/git-flow-cheatsheet/index.pt_BR.html). We use Master as our "competition" code and develop as our main devopment branch. -## Tech +## Dependencies If you are new on this project, you might like to take a look on these stuff: @@ -15,33 +15,20 @@ If you are new on this project, you might like to take a look on these stuff: ## Install -To install this project you just need to `git clone`. Come on, I know you can do that. + To install this project you just need to: + - `git clone` + - `yarn install` inside repository to install all node dependencies ## Requirements - `Node > 8.4.0` - - Being able to sudo, in other words, **YOU FUCKING NEED A LINUX DISTRO** - Have SSL-Vision installed -## Contributing - -Before you start to mess with our code base: - * [install .editorconfig plugin in your editor](https://editorconfig.org/#download) - * [install standard (linter) plugin in your editor](https://standardjs.com/index.html#are-there-text-editor-plugins) - - ## Running -Just type `sudo node server` and press enter in your terminal. Remember to start SSL-Vision `./bin/vision` before do that. +Just type `sudo RUN_MODE=1 node server` and press enter in your terminal. Remember to start SSL-Vision `./bin/vision` before do that. ### SSL-Vision - Remember to set the field control points and configure collors correct ### Simulated Version - - To run the position simulator use `sudo SIMULATED=1 node server` - -### Running The Game Manager - - To run use `sudo node server` - - -### TODO - - Inside Intention/index.js try normalizing weight instead of cropping + - To run the position simulator use `sudo RUN_MODE=2 node server`. Make sure to have [NoPlanVssSimulator](https://github.com/project-neon/NoPlanVssSimulator) diff --git a/config.json b/config.json index 03dfb72..fb24a5e 100644 --- a/config.json +++ b/config.json @@ -1,20 +1,28 @@ { "vision": "ssl-vision", "driver": "serial-driver", - "internal-simulator": true, + "startSide": "left", + "startColor": "blue", "ssl-vision": { "class": "ssl-vision", "port": 10006, "host": "224.5.23.2" }, - "vss-vision": {}, + "simple-simulation-vision": { + "class": "./VSSVision" + }, "serial-driver": { "class": "./SerialClient", "default-port": "/dev/ttyUSB0", "debug": false, "baud-rate": 115200 }, - "mocked-vision": {}, + "simple-simulation-driver": { + "class": "./VSSserialClient" + }, + "mock-driver": { + "class": "./MockDriver" + }, "ui": { "sockets": { "port": 8080 diff --git a/entities/FieldConstraints.js b/entities/FieldConstraints.js index 9df97c7..340c2c1 100644 --- a/entities/FieldConstraints.js +++ b/entities/FieldConstraints.js @@ -2,37 +2,35 @@ module.exports = { LEFT: { x0: -720, y0: -2000, - x1: 720, - y1: 0 - }, - SMALL_AREA_LEFT: { - x0: -720, - y0: 300, - x1: -550, - y1: 600 + x1: -500, + y1: -150 }, RIGHT: { - x0: 0, - y0: 0, - x1: 750, + x0: -720, + y0: 150, + x1: -500, y1: 2000 }, - SMALL_AREA_RIGHT: { - x0: -720, - y0: -602, + GOAL_INNER_AREA: { + x0: -2000, + y0: -520, + x1: -300, + y1: 520 + }, + SMALL_AREA: { + x0: -2000, + y0: -350, x1: -550, - y1: -300 + y1: 350 }, - CENTER: { - x0: 0, - y0: 301, - x1: 700, - y1: 602 + GP: {// Traves + x: 750, + y: 200 }, - SMALL_AREA_CENTER: { - x0: -720, - y0: -300, - x1: -500, - y1: 300 + OUR_AREA: { + x0: -2000, + y0: -720, + x1: 0, + y1: 720 } } diff --git a/lib/Coach.js b/lib/Coach.js index 90701ff..46cc32f 100644 --- a/lib/Coach.js +++ b/lib/Coach.js @@ -1,5 +1,4 @@ const _ = require('lodash') - const GoalKeeper = require('../players/experimental/GoalkeeperMain') const GoalKeeperSides = require('../players/experimental/GoalkeeperSides') const GoalKeeperPush = require('../players/experimental/GoalkeeperPush') @@ -8,66 +7,54 @@ const Attacker = require('../players/experimental/Attacker') const AttackerFoward = require('../players/experimental/AttackerFoward') const AttackerSides = require('../players/experimental/AttackerSides') const AttackerAvoidSides = require('../players/experimental/AttackerAvoidSides') -const midfielderAttacker = require('../players/experimental/MidFieldAttacker') -const midfielderDefender = require('../players/experimental/MidFieldDefender') +const MidfielderAttacker = require('../players/experimental/MidFieldAttacker') +const MidfielderDefender = require('../players/experimental/MidFieldDefender') const RulesPlay = require('../players/experimental/RulePlays') - const Vector = require('../lib/Vector') module.exports = class Coach { - constructor(dependencies) { - this.match = dependencies.match - this.robotsProperties = this.match.robotsProperties - - this.currentOrder = {} - - this.init() + constructor (dependencies) { + this.match = dependencies.match + this.robotsProperties = this.match.robotsProperties + this.currentOrder = {} + this.init() } - async init() { - /* - Inicializa algoritmos e estruturas auxiliares para tomar decisões - */ - this.goalkeeperId = null - this.attackerId = null - this.midfieldId = null - - this.attackerRobot = null - - this.Rules = new RulesPlay(0, this.match, null), - - this.goalkeeper = { - main: new GoalKeeper(0, this.match, null), - push: new GoalKeeperPush(0, this.match, null), - side: new GoalKeeperSides(0, this.match, null) - } - + async init () { + // Inicializa algoritmos e estruturas auxiliares para tomar decisões + this.goalkeeperId = null + this.attackerId = null + this.midfieldId = null + this.attackerRobot = null + this.Rules = new RulesPlay(0, this.match, null) + + this.goalkeeper = { + main: new GoalKeeper(0, this.match, null), + push: new GoalKeeperPush(0, this.match, null), + side: new GoalKeeperSides(0, this.match, null) + } this.attacker = { main: new Attacker(0, this.match, null), foward: new AttackerFoward(0, this.match, null), sides: new AttackerSides(0, this.match, null), avoidSides: new AttackerAvoidSides(0, this.match, null) } - this.midfielder = { - inAttack: new midfielderAttacker(0, this.match, null), - inDefense: new midfielderDefender(0, this.match, null), + inAttack: new MidfielderAttacker(0, this.match, null), + inDefense: new MidfielderDefender(0, this.match, null), sides: new AttackerSides(0, this.match, null), - avoidSides: new AttackerAvoidSides(0, this.match, null) + avoidSides: new AttackerAvoidSides(0, this.match, null) } - - - } insideFieldConstraint (fieldConstraint, ball) { if (ball == null) return false - if (ball.x > fieldConstraint.x0 && ball.x < fieldConstraint.x1 - && ball.y > fieldConstraint.y0 && ball.y < fieldConstraint.y1) return true + if (ball.x > fieldConstraint.x0 && ball.x < fieldConstraint.x1 && + ball.y > fieldConstraint.y0 && ball.y < fieldConstraint.y1) return true return false } - async decide(data, robots) { + async decide (data, robots) { /* Metodo principal de decisão do coach para os robos, atribui aos objetos de robots: @@ -84,10 +71,10 @@ module.exports = class Coach { // id let distFromBallCandidateGK = 100000 - + if (!this.goalkeeperId) { _.values(robots).map(robot => { - if(robot.robots.self.position) { + if (robot.robots.self.position) { const distToGoalCenter = Vector.distBetween({x: -700, y: 0}, robot.robots.self.position) if (distFromBallCandidateGK > distToGoalCenter) { this.goalkeeperId = robot.radioId @@ -98,13 +85,11 @@ module.exports = class Coach { } let distToBallCandidateATK = 1000000 - const ball = this.match.dataManager.ball - _.values(robots).map(robot => { - if (robot.radioId != this.goalkeeperId) { - if(robot.robots.self.position) { - if (!ball){ + if (robot.radioId !== this.goalkeeperId) { + if (robot.robots.self.position) { + if (!ball) { this.attackerId = robot.radioId } else { const distToBall = Vector.distBetween(ball, robot.robots.self.position) @@ -118,7 +103,7 @@ module.exports = class Coach { }) _.values(robots).map(robot => { - if(robot.radioId == this.goalkeeperId) { + if (robot.radioId === this.goalkeeperId) { if (!ball) { robot.runningPlay = this.goalkeeper.main this.goalkeeper.main.setRobot(robot) @@ -126,18 +111,15 @@ module.exports = class Coach { if (this.insideFieldConstraint(FieldConstraints.SMALL_AREA_CENTER, ball)) { robot.runningPlay = this.goalkeeper.push this.goalkeeper.push.setRobot(robot) - - } else if (this.insideFieldConstraint(FieldConstraints.SMALL_AREA_LEFT, ball) - || this.insideFieldConstraint(FieldConstraints.SMALL_AREA_RIGHT, ball)) { + } else if (this.insideFieldConstraint(FieldConstraints.SMALL_AREA_LEFT, ball) || + this.insideFieldConstraint(FieldConstraints.SMALL_AREA_RIGHT, ball)) { robot.runningPlay = this.goalkeeper.side this.goalkeeper.side.setRobot(robot) - } else { robot.runningPlay = this.goalkeeper.main this.goalkeeper.main.setRobot(robot) } - } - else if(robot.radioId == this.attackerId) { + } else if (robot.radioId === this.attackerId) { this.attackerRobot = robot let robotPos = robot.robots.self.position let ball = {x: this.match.dataManager.ball.x, y: this.match.dataManager.ball.y} @@ -148,21 +130,17 @@ module.exports = class Coach { if (robotPos.x < ball.x) { robot.runningPlay = this.attacker.sides this.attacker.sides.setRobot(robot) - } else { robot.runningPlay = this.attacker.avoidSides this.attacker.avoidSides.setRobot(robot) - } - - } else if(Math.abs(angle) < 25) { + } else if (Math.abs(angle) < 25) { robot.runningPlay = this.attacker.foward this.attacker.foward.setRobot(robot) } else { robot.runningPlay = this.attacker.main this.attacker.main.setRobot(robot) } - } else { // MEIO CAMPISTA let robotPos = robot.robots.self.position @@ -178,13 +156,12 @@ module.exports = class Coach { robot.runningPlay = this.midfielder.avoidSides this.midfielder.avoidSides.setRobot(robot) } - }else{ + } else { robot.runningPlay = this.midfielder.inDefense this.midfielder.inDefense.setRobot(robot) } } } - }) } } diff --git a/lib/Comm.js b/lib/Comm.js index 5b99ff3..bf259f1 100644 --- a/lib/Comm.js +++ b/lib/Comm.js @@ -1,8 +1,4 @@ -const _ = require('lodash') -const path = require('path') - -module.exports = function(match, options){ - +module.exports = function (match, options) { var express = require('express') var app = express() var path = require('path') @@ -11,40 +7,33 @@ module.exports = function(match, options){ var favicon = require('serve-favicon') server.listen(options.PORT) - - app.use(favicon(path.join(__dirname,'/../static/favicon.ico'))) - - app.use(express.static(path.join(__dirname,'/../static'))) - + app.use(favicon(path.join(__dirname, '/../static/favicon.ico'))) + app.use(express.static(path.join(__dirname, '/../static'))) app.get('/', function (req, res) { - res.sendFile(path.join(__dirname + '/../static/index.html')) + res.sendFile(path.join(__dirname, '/../static/index.html')) }) - - match.dataManager.vision.on('detection',(detection) => { - // console.log(mapDict(match.worker.workers, x => x.getIntentionsInfo())['robo_1']) + match.dataManager.vision.on('detection', (detection) => { io.sockets.emit( - 'detection', - { - 'detection': detection, - 'intentions': {}//mapDict(match.worker.workers, x => x.getIntentionsInfo()) - } - ) - + 'detection', + { + 'detection': detection, + 'intentions': {} + } + ) }) - io.on('connection', function (socket) { socket.on('state', function (data) { - if (data.state == "toggle") { - if(match.state.state.status == "running"){ - match.state.setState({status:"stopped"}) - } else { - match.state.setState({status:"running"}) + if (data.state === 'toggle') { + if (match.state.state.status === 'running') { + match.state.setState({status: 'stopped'}) + } else { + match.state.setState({status: 'running'}) } } - if (data.type == "side") { + if (data.type === 'side') { match.state.setState({side: data.state}) } - if (data.type == "color") { + if (data.type === 'color') { match.state.setState({team: data.state}) } }) diff --git a/lib/DataManager.js b/lib/DataManager.js index f889513..6fb7169 100644 --- a/lib/DataManager.js +++ b/lib/DataManager.js @@ -1,28 +1,25 @@ -const _ = require('lodash') const EventEmitter = require('events') const Vector = require('./Vector') -module.exports = class DataManager extends EventEmitter{ - constructor(match) { - super() - +module.exports = class DataManager extends EventEmitter { + constructor (match) { + super() this.match = match this.robots = null - this.coach = null + this.coach = null - this.frameHistory = { - size: 15, - frames: [] - } + this.frameHistory = { + size: 15, + frames: [] + } - // this.vision = vision.impl - // this.driver = driver.impl this.visionParams = match.options.vision.params this.driverParams = match.options.driver.params } - async init () { - this.vision = require(this.visionParams.class) + async init () { + this.vision = require(this.visionParams.class) + this.driver = require(this.driverParams.class) this.vision = new this.vision(this.visionParams.host, this.visionParams.port) @@ -36,39 +33,58 @@ module.exports = class DataManager extends EventEmitter{ this.vision.on('detection', this.emitVision.bind(this)) } - getBallProjection(goalLine=-630) { + getBallProjection(goalLine=-680, robot) { let ballPos = {x: this.ball.x, y: this.ball.y} - let ballSpeed = this.ball.speed + let ballSpeed = this.ball.speed let ballDir = Vector.norm(ballSpeed) let BallAngle = Math.abs(Vector.angle(ballDir)) + + // 1||-1 * angulo da bola (em y) * let ballProjectY = -1 * (ballDir.y/Math.abs(ballDir.y)) * Math.tan(BallAngle) * Math.abs(ballPos.x - goalLine) + ballPos.y - return {x: goalLine, y: ballProjectY} } + getLastBall() { + if(this.frameHistory.frames.length > 0) { + return this.frameHistory.frames[0].balls[0] + } + return {'x': 0, 'y': 0} + } + emitVision (frame) { + // let side = this.match.state.state.side + // cleanData['right'] = this.fixFrame(frame, 'right') + // cleanData['left'] = this.fixFrame(frame, 'left') let data = frame - let side = this.match.state.state.side - data = this.fixFrame(data, side) this.updateFrameHistory(frame) data['cleanData'] = {} // TODO quando houverem mais tratamentos fazer algo mais elaborado if (data.balls.length > 0) { - data['cleanData']['ball'] = { - 'x': data.balls[0]['x'], - 'y': data.balls[0]['y'], - 'speed': this.calculateBallSpeed() - } + this.ball = frame.balls[0] + }else { + this.ball = this.getLastBall() + } - this.ball = data['cleanData']['ball'] - if (this.frameHistory.frames.length > 1){ - let ballProjection = this.getBallProjection() - this.ball['projection'] = ballProjection - } + this.ball = { + 'x': this.ball['x'], + 'y': this.ball['y'], + 'speed': this.calculateBallSpeed() } - + + if (this.frameHistory.frames.length > 1){ + let ballProjection = this.getBallProjection() + this.ball['projection'] = ballProjection + } + + data['cleanData']['ball'] = this.ball + + data = { + 'right': this.fixFrame(frame, 'right'), + 'left': this.fixFrame(frame, 'left') + } + this.emit('detection', data) } @@ -84,72 +100,18 @@ module.exports = class DataManager extends EventEmitter{ //1551562891.27858 - 1551562891.246445/ } - calculateBallSpeed () { - if (this.frameHistory.frames.length <= 1) return - // TODO: zip e clone poderiam estar num arquivo de metodos uteis - let zip = (rows) => rows[0].map((_,c) => rows.map(row => row[c])) - - let clone = (obj) => { - if (null == obj || "object" != typeof obj) return obj - var copy = obj.constructor() - for (var attr in obj) { - if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr] - } - return copy - } - let frameHistoryShifted = clone(this.frameHistory.frames) - frameHistoryShifted.shift() - let zipFrames = zip([this.frameHistory.frames, frameHistoryShifted]) - zipFrames.pop() - - // const direction = Vector.norm({ - // x: (zipFrames[0][0].balls[0].x + 10000) - (zipFrames[0][1].balls[0].x + 10000), - // y: (zipFrames[0][0].balls[0].y + 10000) - (zipFrames[0][1].balls[0].y + 10000) - // }) - - let speeds = [] - for (let pairs in zipFrames) { - // pairs[0] - // pairs[1] - let ballPosF = { - x: zipFrames[pairs][0].balls[0].x, - y: zipFrames[pairs][0].balls[0].y - } - let ballPosI = { - x: zipFrames[pairs][1].balls[0].x, - y: zipFrames[pairs][1].balls[0].y - } - - // const deltaPos = Math.abs( - // Math.sqrt(Math.pow(ballPosF.x - ballPosI.x, 2) + Math.pow(ballPosF.y - ballPosI.y, 2)) - // ) - - const deltaPos = {x: ballPosF.x - ballPosI.x, y: ballPosF.y - ballPosI.y} - - let frameTimeF = zipFrames[pairs][0].t_capture - let frameTimeI = zipFrames[pairs][1].t_capture - const deltaTime = (frameTimeF - frameTimeI)*10 //to Seconds - const speed = { - x: (deltaPos.x) / deltaTime, - y: (deltaPos.y) / deltaTime - } // [mm/s] - speeds.push(speed) - } - speeds.shift() - let finalSpeed = speeds.reduce(function(a, b) { return {x: a.x + b.x, y: a.y + b.y};}, {x: 0, y:0}) - finalSpeed = {x: finalSpeed.x/speeds.length, y: finalSpeed.y/speeds.length} - const direction = Vector.norm(finalSpeed) - return finalSpeed - } - fixFrame(frame, side) { + fixFrame(frame_, side) { // Fix position and orientation from robots and ball: // Position just multiply by -1 (since the center of the field is the origin) // Orientation just sum PI (a 180 degrees rotation) + + let frame = JSON.parse(JSON.stringify(frame_)) if(side == 'left') { let yellow_team = frame['robots_yellow'] let blue_team = frame['robots_blue'] let balls = frame['balls'] + let cleanData = frame.cleanData if (blue_team.length > 0) { for(let robot in blue_team) { @@ -173,11 +135,79 @@ module.exports = class DataManager extends EventEmitter{ } } + if (cleanData.ball) { + let ball = cleanData.ball + ball.x *= -1 + ball.y *= -1 + if(ball.speed){ + ball.speed = Vector.mult(ball.speed, -1) + } + if(ball.projection) { + ball.projection = Vector.mult(ball.projection, -1) + } + } + frame['robots_yellow'] = yellow_team frame['robots_blue'] = blue_team frame['balls'] = balls + } + return frame } - return frame - } -} + + updateFrameHistory (frame) { + if (frame.balls.length === 0) return + // Ponto final no cálculo do vetor é a primeira posição do array + if (this.frameHistory.frames.length === this.frameHistory.size) { + this.frameHistory.frames.pop() + this.frameHistory.frames.unshift(frame) + } else { + this.frameHistory.frames.unshift(frame) + } + } + calculateBallSpeed () { + if (this.frameHistory.frames.length <= 1) return + // TODO: zip e clone poderiam estar num arquivo de metodos uteis + let zip = (rows) => rows[0].map((_, c) => rows.map(row => row[c])) + + let clone = (obj) => { + if (obj == null || typeof obj !== 'object') return obj + var copy = obj.constructor() + for (var attr in obj) { + if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr] + } + return copy + } + let frameHistoryShifted = clone(this.frameHistory.frames) + frameHistoryShifted.shift() + let zipFrames = zip([this.frameHistory.frames, frameHistoryShifted]) + zipFrames.pop() + + let speeds = [] + for (let pairs in zipFrames) { + let ballPosI = { + x: zipFrames[pairs][0].balls[0].x, + y: zipFrames[pairs][0].balls[0].y + } + let ballPosF = { + x: zipFrames[pairs][1].balls[0].x, + y: zipFrames[pairs][1].balls[0].y + } + + const deltaPos = {x: ballPosF.x - ballPosI.x, y: ballPosF.y - ballPosI.y} + + let frameTimeF = zipFrames[pairs][0].t_capture + let frameTimeI = zipFrames[pairs][1].t_capture + const deltaTime = (frameTimeF - frameTimeI) * 10 // to Seconds + const speed = { + x: (deltaPos.x) / deltaTime, + y: (deltaPos.y) / deltaTime + } + speeds.push(speed) + } + let finalSpeed = speeds.reduce(function (a, b) { return {x: a.x + b.x, y: a.y + b.y} }, {x: 0, y: 0}) + finalSpeed = {x: finalSpeed.x / speeds.length, y: finalSpeed.y / speeds.length} + return finalSpeed + } + +} \ No newline at end of file diff --git a/lib/DumbCoach.js b/lib/DumbCoach.js new file mode 100644 index 0000000..572ea87 --- /dev/null +++ b/lib/DumbCoach.js @@ -0,0 +1,76 @@ +const _ = require('lodash') + +const TestPlay = require('../players/tests/PointIntentionPlayer') +const GoalKeeper = require('../roles/GoalkeeperRole') +const Attacker = require('../roles/AttackerRole') + + + +module.exports = class Coach { + constructor(dependencies) { + this.match = dependencies.match + this.robotsProperties = this.match.robotsProperties + + this.currentOrder = {} + + this.goalKeeper = null + + this.init() + } + + + insideFieldConstraint (fieldConstraint, ball) { + if (ball == null) return false + if (ball.x > fieldConstraint.x0 && ball.x < fieldConstraint.x1 + && ball.y > fieldConstraint.y0 && ball.y < fieldConstraint.y1) return true + return false + } + + async init() { + /* + Inicializa algoritmos e estruturas auxiliares para tomar decisões + */ + this.dumbRobots = [ + new TestPlay(0, this.match, null), + new TestPlay(0, this.match, null), + new TestPlay(0, this.match, null), + new TestPlay(0, this.match, null), + new TestPlay(0, this.match, null), + new TestPlay(0, this.match, null) + ] + + this.goalKeeper = new GoalKeeper(this.match) + this.attacker = new Attacker(this.match) + + this.attacker2 = new Attacker(this.match) + } + + async decide(data, robots) { + /* + Metodo principal de decisão do coach para os robos, atribui aos objetos de + robots: + - running_play: a Play vigente que sera executada pelo robot naquela iteração + - robots: um dicionario contento 3 elementos relativos aos dados dos robos: + * self: dados referentes ao proprio robo + * teammate: lista de elementos referentes aos dados dos robos de mesmo time + * foes: lista de elementos robos referentes aos dados dos robos adversarios + + @param data Dados tratados pelo dataManager + @param robots ultima iteração de robots. + */ + // options {visionId, radioId} + // id + + let it = 0 + _.values(robots).map(robot => { + if (robot.radioId == 1) { + this.goalKeeper.decidePlay(robot, data) + } else if (robot.radioId == 2) { + this.attacker.decidePlay(robot, data) + } else { + this.attacker2.decidePlay(robot, data) + } + it += 1 + }) + } +} diff --git a/lib/GameManager.js b/lib/GameManager.js index 44559ad..f0c2482 100644 --- a/lib/GameManager.js +++ b/lib/GameManager.js @@ -1,21 +1,16 @@ const _ = require('lodash') -const dataManager = require('./DataManager') - module.exports = class GameManager { - constructor(match) { + constructor (match) { this.match = match - this.robotsProperties = this.match.robotsProperties - - this.dataManager = this.match.dataManager - this.robots = null - this.coach = null + this.coaches = [] } - async startRobot(id, property) { - this.robots[id] = { + async startRobot (id, property, teamId) { + this.robots[id + 100*teamId] = { + teamId: teamId, radioId: property.radio_id, visionId: property.vision_id, runningPlay: null, @@ -24,56 +19,79 @@ module.exports = class GameManager { self: {}, teammate: [], foes: [] - }, + } } } - async init() { - // Make sure to initialize only once - // if (this.initialized) - // throw new Error('Cannot re-initialize RobotWorkers') - // this.initialized = true - + async init () { // Initialize robots this.robots = {} - for (let id in this.robotsProperties) { - console.log('RobotWorkers', 'start', id) - await this.startRobot(id, this.robotsProperties[id]) + for (let teamId in this.robotsProperties){ + for (let id in this.robotsProperties[teamId]) { + console.log('RobotWorkers', 'start', 'robot :'+id, 'team :'+teamId) + await this.startRobot(id, this.robotsProperties[teamId][id], teamId) + } } - this.coach = new this.match.options.coach({match: this.match}) - + for (let teamId in this.match.options.coaches){ + this.coaches[teamId] = new this.match.options.coaches[teamId]({match: this.match}) + } // Bind: Everytime vision detects something, call update inside this.dataManager.on('detection', this.update.bind(this)) } // Calls update on all robots - async update(data) { - // // Fix position and orientation based on side + async update (data) { + // Fix position and orientation based on side // Get team color - let team = this.match.state.state.team - // console.log(side) - let robots_pos = data['robots_' + team] - // Iterare all workers + let mainTeamSide = this.match.state.state.side + let rivalTeamSide = mainTeamSide == 'right' ? 'left' : 'right' + let sides = [mainTeamSide, rivalTeamSide] + + let mainTeamColor = this.match.state.state.team + let rivalTeamColor = mainTeamColor == 'blue' ? 'yellow' : 'blue' + // Iterare all robots + let mainTeamRobots = [] + let rivalTeamRobots = [] + _.values(this.robots).map(robot => { // Find specific robot state - let detection = _.find(robots_pos, {robot_id: robot.visionId}) + let teamId = robot.teamId + let teamData = data[sides[teamId]] + if (teamId == 0) { + mainTeamRobots.push(robot) + } else { + rivalTeamRobots.push(robot) + } + + let teamColor = teamId == 0? mainTeamColor : rivalTeamColor + let robotsPos = teamData['robots_' + teamColor] + + let detection = _.find(robotsPos, {robot_id: robot.visionId}) // Set worker position and orientation if (detection) { robot.robots.self['position'] = {x: detection.x, y: detection.y} robot.robots.self['orientation'] = detection.orientation robot.robots.self['detection'] = detection } - if (data) { - robot.robots.self.frame = data + if (teamData) { + robot.robots.self.frame = teamData } }) - await this.coach.decide(data, this.robots) + await this.coaches[0].decide(data[sides[0]], mainTeamRobots) + + if (this.coaches.length > 1){ + await this.coaches[1].decide(data[sides[1]], rivalTeamRobots) + } let promises = _.values(this.robots).map(robot => { + let teamId = robot.teamId + let teamData = data[sides[teamId]] + let teamColor = teamId == 0? mainTeamColor : rivalTeamColor + let robotsPos = teamData['robots_' + teamColor] - let detection = _.find(robots_pos, {robot_id: robot.visionId}) + let detection = _.find(robotsPos, {robot_id: robot.visionId}) if (detection) { robot.runningPlay.position = {x: detection.x, y: detection.y} @@ -83,19 +101,16 @@ module.exports = class GameManager { } else { robot.runningPlay.active = false } - if (data) { - robot.runningPlay.frame = data + if (teamData) { + robot.runningPlay.frame = teamData } // Delegate update method to robots return robot.runningPlay.update() }) // Wait all promises to finish - Promise.all(promises).then(data => { - console.log(data) - this.dataManager.driver.send(data) + Promise.all(promises).then(robotData => { + this.dataManager.driver.send(robotData) }) } - - } diff --git a/lib/Match.js b/lib/Match.js index ab67ac1..6a1b3a7 100644 --- a/lib/Match.js +++ b/lib/Match.js @@ -1,36 +1,29 @@ const _ = require('lodash') -const SSLVision = require('ssl-vision') const StateManager = require('./StateManager') -const SerialClient = require('./SerialClient') -const RobotWorkers = require('./RobotWorkers') - const DataManager = require('./DataManager') const GameManager = require('./GameManager') module.exports = class Match { - constructor(options) { + constructor (options) { // Match tem que ter uma instancia de GameManager, DataManager, state this.options = _.defaults(options, { driver: {}, vision: {}, coach: {}, - robotsProperties: {} + robotsProperties: {}, + matchParams : {} }) this.state_ = null - + this.matchParams = options.matchParams this.dataManager = null this.gameManager = null - this.robotsProperties = options.robotsProperties } - async init() { - if (this.initialized) - throw new Error('Cannot re-initialize Match') - + async init () { + if (this.initialized) throw new Error('Cannot re-initialize Match') this.initialized = true - console.log('Match init') await this.initState() console.log('DataManager init') @@ -40,54 +33,22 @@ module.exports = class Match { console.log('Finished init') } - async initState() { + async initState () { this.state = new StateManager({ status: 'stopped', - team: 'blue', - side: 'left', + team: this.matchParams.startColor, + side: this.matchParams.startSide }) } - async initGameManager() { + async initGameManager () { this.gameManager = new GameManager(this) - this.gameManager.init() } - async initDataManager() { - + async initDataManager () { this.dataManager = new DataManager(this) - this.dataManager.init() } - // async initDriver() { - // this.driver = new SerialClient(this.options.driver) - // // Wait be ready - // await this.driver.connect() - // console.log('Waiting driver startup') - // await this.driver.ready() - // console.log('Startup complete') - - // } - - // async initVision() { - // // let options = this.options.vision - // // this.vision = new SSLVision(options.HOST, options.PORT) - // // // Wait be ready - // // await this.vision.connect() - - // this.vision = new VSSVision('localhost', options.PORT) - // await this.vision.connect() - // } - - // async initWorkers() { - // this.worker = new RobotWorkers(this, this.options.robots) - // // Wait be ready - // await this.worker.init() - // } - - // async initSocket() { - // this.socket = new Socket() - // } } diff --git a/lib/MatchSimulated.js b/lib/MatchSimulated.js index e87dece..e5f924a 100644 --- a/lib/MatchSimulated.js +++ b/lib/MatchSimulated.js @@ -1,25 +1,19 @@ const _ = require('lodash') -// const SSLVision = require('ssl-vision') - const EventEmitter = require('events') - const StateManager = require('./StateManager') -const SerialClient = require('./SerialClient') const RobotWorkers = require('./RobotWorkers') module.exports = class Match { - constructor(options) { + constructor (options) { this.options = _.defaults(options, { driver: {}, vision: {simulation_step: 0.03}, - robots: {}, + robots: {} }) - this.state = null this.driver = null this.vision = null this.workers = null - this.ball = { confidence: 0.7377133369445801, area: 118, @@ -31,12 +25,9 @@ module.exports = class Match { } } - async init() { - if (this.initialized) - throw new Error('Cannot re-initialize MatchSimulated') - + async init () { + if (this.initialized) throw new Error('Cannot re-initialize MatchSimulated') this.initialized = true - console.log('Match init') await this.initState() console.log('Driver init') @@ -48,36 +39,34 @@ module.exports = class Match { console.log('Finished init') } - async initState() { + async initState () { this.state = new StateManager({ status: 'stopped', team: 'blue', - side: 'right', + side: 'right' }) } - async initDriver() { + async initDriver () { this.driver = { send: async (robotId, robotState, linearSpeed, angularSpeed) => {} } } - async initVision() { - let simulation_step = this.options.vision.simulation_step || 0.03 + async initVision () { + let simulationStep = this.options.vision.simulation_step || 0.03 this.vision = new EventEmitter() let frame = 0 let time = 0 setInterval(() => { let robots = this.worker.workers - let robotPackets = [] for (let key in robots) { let robot = robots[key] if (robot.simulate) { // Simulate the robot - robot.simulate(simulation_step) - + robot.simulate(simulationStep) // Build robot packet robotPackets.push({ confidence: 1, @@ -92,7 +81,7 @@ module.exports = class Match { } // Build root packet - time += simulation_step + time += simulationStep let packet = { frame_number: frame++, t_capture: time, @@ -102,21 +91,16 @@ module.exports = class Match { this.ball ], robots_yellow: [], - robots_blue: robotPackets, + robots_blue: robotPackets } - // Emit Detection packet this.vision.emit('detection', packet) - }, simulation_step * 1000) + }, simulationStep * 1000) } - async initWorkers() { + async initWorkers () { this.worker = new RobotWorkers(this, this.options.robots) // Wait be ready await this.worker.init() } - - async initSocket() { - this.socket = new Socket() - } } diff --git a/lib/MatchVSSSimulated.js b/lib/MatchVSSSimulated.js index 302eb20..61174e6 100644 --- a/lib/MatchVSSSimulated.js +++ b/lib/MatchVSSSimulated.js @@ -1,17 +1,15 @@ const _ = require('lodash') -const SSLVision = require('ssl-vision') - const VSSVision = require('./VSSVision') const StateManager = require('./StateManager') const VSSSerialClient = require('./VSSserialClient') const RobotWorkers = require('./RobotWorkers') module.exports = class Match { - constructor(options) { + constructor (options) { this.options = _.defaults(options, { driver: {}, vision: {}, - robots: {}, + robots: {} }) this.state = null @@ -20,9 +18,8 @@ module.exports = class Match { this.workers = null } - async init() { - if (this.initialized) - throw new Error('Cannot re-initialize Match') + async init () { + if (this.initialized) { throw new Error('Cannot re-initialize Match') } this.initialized = true @@ -37,31 +34,27 @@ module.exports = class Match { console.log('Finished init') } - async initState() { + async initState () { this.state = new StateManager({ status: 'stopped', team: 'yellow', - side: 'left', + side: 'left' }) } - async initDriver() { + async initDriver () { this.driver = new VSSSerialClient({PORT: 5778, HOST: 'localhost'}) this.driver.connect() } - async initVision() { + async initVision () { this.vision = new VSSVision('localhost', 5777) await this.vision.connect() } - async initWorkers() { + async initWorkers () { this.worker = new RobotWorkers(this, this.options.robots) // Wait be ready await this.worker.init() } - - async initSocket() { - this.socket = new Socket() - } } diff --git a/lib/MockDriver.js b/lib/MockDriver.js new file mode 100644 index 0000000..7e8ce24 --- /dev/null +++ b/lib/MockDriver.js @@ -0,0 +1,18 @@ + +const _ = require('lodash') + +const EventEmitter = require('events') + +module.exports = class SerialClient extends EventEmitter { + constructor (options) { + super() + } + + async ready() {} + + async connect (serialPort) {} + + async send (data) { + console.log(data) + } +} diff --git a/lib/RobotWorkers.js b/lib/RobotWorkers.js index 04e9396..f47cf98 100644 --- a/lib/RobotWorkers.js +++ b/lib/RobotWorkers.js @@ -1,42 +1,33 @@ const _ = require('lodash') -// const dataManager = require('./DataManager') module.exports = class RobotWorkers { - constructor(match, robots) { + constructor (match, robots) { this.match = match this.robots = robots this.workers = {} - // this.dataManager = new dataManager } - async init() { + async init () { // Make sure to initialize only once - if (this.initialized) - throw new Error('Cannot re-initialize RobotWorkers') + if (this.initialized) throw new Error('Cannot re-initialize RobotWorkers') this.initialized = true - // Initialize robots for (let id in this.robots) { console.log('RobotWorkers', 'start', id) await this.start(id, this.robots[id]) } - // Bind: Everytime vision detects something, call update inside this.match.vision.on('detection', this.update.bind(this)) } // Calls update on all robots - async update(frame) { + async update (frame) { // Fix position and orientation based on side let side = this.match.state.state.side - console.log(side) frame = this.dataManager.fixFrame(frame, side) // Get team color let team = this.match.state.state.team - // console.log(side) let robots = frame['robots_' + team] - // console.log(frame) - // Iterare all workers let promises = _.values(this.workers).map(worker => { // Find specific robot state @@ -64,14 +55,10 @@ module.exports = class RobotWorkers { }) } - async start(id, options) { - if (this.workers[id]) { - throw new Error('Cannot start process. Process already running:' + id) - } - + async start (id, options) { + if (this.workers[id]) throw new Error('Cannot start process. Process already running:' + id) // Instantiate RobotWorker class let worker = new options.class(id, this.match, options) - // Register worker inside this.workers[id] = worker } diff --git a/lib/SerialClient.js b/lib/SerialClient.js index daeefc5..2ec009d 100644 --- a/lib/SerialClient.js +++ b/lib/SerialClient.js @@ -199,4 +199,4 @@ async function getPort(prefered) { }) return answer.port -} +} \ No newline at end of file diff --git a/lib/SimpleSimulationVision.js b/lib/SimpleSimulationVision.js new file mode 100644 index 0000000..b102065 --- /dev/null +++ b/lib/SimpleSimulationVision.js @@ -0,0 +1,92 @@ +const dgram = require('dgram') +const EventEmitter = require('events') + +module.exports = class VSSVision extends EventEmitter { + + constructor(HOST, PORT, dataManager) { + super() + this.robotPackets + this.dataManager = dataManager + this.data = null + this.frame = 0 + this.time = 0 + this.ball = { + confidence: 1, + area: 120, + x: 0, + y: 0, + z: 0, + pixel_x: 323.2542419433594, + pixel_y: 387.22882080078125 + } + } + + connect () { + return new Promise((resolve, reject) => {}) + } + + _init() { + let simulation_step = 0.03 + setInterval(() => { + let robots = this.dataManager.match.gameManager.robots + for (let key in robots) { + let robot = robots[key] + // if (robot.simulate) { + // Simulate the robot + robot.running_play.simulate(simulation_step) + + // Build robot packet + this.robotPackets.push({ + confidence: 1, + robot_id: robot.visionId, + x: robot.robots.self['position'].position.x, + y: robot.robots.self['position'].position.y, + orientation: robot.robots.self['position'].orientation, + pixel_x: 0, + pixel_y: 0 + }) + // } + } + this.time += simulation_step + let packet = { + frame_number: this.frame++, + t_capture: this.time, + t_sent: this.time, + camera_id: 1, + balls: [ + this.ball + ], + robots_yellow: [], + robots_blue: this.robotPackets, + } + + this._message(packet) + }, simulation_step * 1000) + } + + _bind() { + } + + _message(data) { + try { + this.data = JSON.parse(data.toString()) + + // Skip if frame is null + if (!this.data) + return + + // Emit data + this.emit('data', this.data) + + // Emit detection only if set + if (this.data.detection) + this.emit('detection', this.data.detection) + + // Emit geometry only if set + if (this.data.geometry) + this.emit('geometry', this.data.geometry) + } catch (e) { + this.emit('error', e) + } + } +} diff --git a/lib/Simulation.js b/lib/Simulation.js deleted file mode 100644 index 91e1939..0000000 --- a/lib/Simulation.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = class Simulation { - - -} diff --git a/lib/StateManager.js b/lib/StateManager.js index ff4afce..98d9ed0 100644 --- a/lib/StateManager.js +++ b/lib/StateManager.js @@ -1,20 +1,19 @@ const EventEmitter = require('events') -module.exports = class StateManager extends EventEmitter{ +module.exports = class StateManager extends EventEmitter { constructor (initialState) { super() this._state = initialState } - setState(object) { + setState (object) { for (let key in object) { this._state[key] = object[key] } - this.emit('change', this._state) } - get state() { + get state () { return this._state } -} \ No newline at end of file +} diff --git a/lib/TensorMath.js b/lib/TensorMath.js index 02390f6..6fe9179 100644 --- a/lib/TensorMath.js +++ b/lib/TensorMath.js @@ -1,5 +1,5 @@ class TensorMath { - static get new() { + static get new () { return new TensorMath() } @@ -7,118 +7,127 @@ class TensorMath { this.operations = [] } - run(x) { - return this.operations.reduce((anterior, op) => op(anterior), x) + run (x) { + return this.operations.reduce((anterior, op) => op(anterior), x) } - sum(val) { + sum (val) { this.operations.push(x => x + val) return this } - sub(val) { + sub (val) { this.operations.push(x => x - val) return this } - mult(val) { + mult (val) { this.operations.push(x => x * val) return this } - div(val) { + div (val) { this.operations.push(x => x / val) return this } - constant(val) { + constant (val) { this.operations.push(x => val) return this } - max(val) { + max (val) { this.operations.push(x => Math.max(x, val)) return this } - - min(val) { + + min (val) { this.operations.push(x => Math.min(x, val)) return this } - inverse() { + inverse () { this.operations.push(x => 1 / x) return this } - pow(val = 2) { + pow (val = 2) { this.operations.push(x => Math.pow(x, val)) return this } - sqrt(val) { + sqrt (val) { this.operations.push(x => Math.sqrt(x)) return this } - constant(val) { + constant (val) { this.operations.push(x => val) return this } - map(minIn, maxIn, minOut, maxOut) { + map (minIn, maxIn, minOut, maxOut) { this.operations.push(x => (x - minIn) * (maxOut - minOut) / (maxIn - minIn) + minOut) return this } - deadWidth(w) { + deadWidth (w) { // w = w / 2 this.operations.push(x => { - if (x <= w) - return 0; - return x; + if (x <= w) { return 0 } + return x }) return this } - constrain(max, min = -max) { + constrain (max, min = -max) { console.log('max:', max, 'min:', min) this.operations.push(x => x < 0 ? Math.max(x, min) : Math.min(x, max)) return this } - crop(max, min = -max) { + crop (max, min = -max) { this.operations.push(x => x < min ? 0 : (x > max ? 0 : x)) return this } + // Rampa de aceleração para se aproximar da bola + sigmoid () { + this.operations.push(x => (1/(1 + Math.exp(-(10*x -6))))) + return this + } - toFixed(n) { + sin () { + this.operations.push(x => Math.sin(x)) + return this + } + + toFixed (n) { this.operations.push(x => x.toFixed(n)) return this } - binarize(max) { + binarize (max) { this.operations.push(x => x < 0 ? -max : (x > 0 ? max : 0)) return this } - easeInOut() { + easeInOut () { this.operations.push(t => t * t * (3 - (2 * t))) return this } - abs() { + abs () { this.operations.push(x => Math.abs(x)) - return this + return this } - get finish() { + get finish () { return this.run.bind(this) } - static buildTensor(start, end, step = 0.01) { + static buildTensor (start, end, step = 0.01) { let tensor = [] - for(let k = start; k < end; k += step) { + for (let k = start; k < end; k += step) { tensor.push(k) } tensor.apply = (fn) => tensor.map(fn) @@ -126,4 +135,4 @@ class TensorMath { } } -module.exports = TensorMath \ No newline at end of file +module.exports = TensorMath diff --git a/lib/TrainingCoach.js b/lib/TrainingCoach.js new file mode 100644 index 0000000..6ffe12d --- /dev/null +++ b/lib/TrainingCoach.js @@ -0,0 +1,52 @@ +const _ = require('lodash') + +const PointTestPlay = require('../players/tests/PointIntentionPlayer') +const LineTestPlay = require('../players/tests/LineIntentionPlayer') +const LookAtTestPlay = require('../players/tests/LookAtIntentionPlayer') + + + +module.exports = class Coach { + constructor(dependencies) { + this.match = dependencies.match + this.robotsProperties = this.match.robotsProperties + + this.currentOrder = {} + + this.init() + } + + + insideFieldConstraint (fieldConstraint, ball) { + if (ball == null) return false + if (ball.x > fieldConstraint.x0 && ball.x < fieldConstraint.x1 + && ball.y > fieldConstraint.y0 && ball.y < fieldConstraint.y1) return true + return false + } + + async init() { + /* + Inicializa algoritmos e estruturas auxiliares para tomar decisões + */ + + this.point = new PointTestPlay(0, this.match, null) + this.line = new LineTestPlay(0, this.match, null) + this.lookat = new LookAtTestPlay(0, this.match, null) + } + + async decide(data, robots) { + // let actualTest = this.point + // let actualTest = this.line + let actualTest = this.lookat + + let it = 0 + + _.values(robots).map(robot => { + if (it == 0) { + robot.runningPlay = actualTest + actualTest.setRobot(robot) + } + it += 1 + }) + } +} diff --git a/lib/VSSClient.js b/lib/VSSClient.js index 3dc5707..8318135 100644 --- a/lib/VSSClient.js +++ b/lib/VSSClient.js @@ -2,14 +2,11 @@ const dgram = require('dgram') const EventEmitter = require('events') module.exports = class VSSClient extends EventEmitter { - - constructor(HOST, PORT) { + constructor (HOST, PORT) { super() - this.HOST = HOST || 'localhost' this.PORT = PORT || 5777 this.client = null - // Public state variables this.data = null } @@ -19,49 +16,35 @@ module.exports = class VSSClient extends EventEmitter { if (this.client) { throw new Error('Client is already open. Close the connection first') } - // Create Client this.client = dgram.createSocket('udp4') - // Bind message this._bind() - // Wait to bind this.client.bind(this.PORT, this.HOST, () => { // Initialize connection this._init() - // Resolve resolve() }) }) } - _init() { - var address = this.client.address() - } - - _bind() { + _bind () { this.client.on('message', this._message.bind(this)) } - _message(data, remote) { + _message (data) { try { this.data = JSON.parse(data.toString('utf8')) // Skip if frame is null - if (!this.data) - return - + if (!this.data) return // Emit data this.emit('data', this.data) - // Emit detection only if set - if (this.data.detection) - this.emit('detection', this.data.detection) - + if (this.data.detection) this.emit('detection', this.data.detection) // Emit geometry only if set - if (this.data.geometry) - this.emit('geometry', this.data.geometry) + if (this.data.geometry) this.emit('geometry', this.data.geometry) } catch (e) { this.emit('error', e) } diff --git a/lib/VSSVision.js b/lib/VSSVision.js index f88cf4b..3bd7667 100644 --- a/lib/VSSVision.js +++ b/lib/VSSVision.js @@ -2,15 +2,12 @@ const dgram = require('dgram') const EventEmitter = require('events') module.exports = class VSSVision extends EventEmitter { - - constructor(HOST, PORT) { + constructor (HOST, PORT) { super() this.HOST = HOST || 'localhost' this.PORT = PORT || 5777 this.client = null - - // Public state variables this.data = null } @@ -18,10 +15,8 @@ module.exports = class VSSVision extends EventEmitter { return new Promise((resolve, reject) => { // Create Client this.client = dgram.createSocket('udp4') - // Bind message this._bind() - // Wait to bind this.client.bind(this.PORT, this.HOST, () => { // Initialize connection @@ -33,32 +28,26 @@ module.exports = class VSSVision extends EventEmitter { }) } - _init() { + _init () { this.client.setBroadcast(true) } - _bind() { + _bind () { this.client.on('message', this._message.bind(this)) } - _message(data, remote) { + _message (data) { try { this.data = JSON.parse(data.toString()) // Skip if frame is null - if (!this.data) - return - + if (!this.data) { return } // Emit data this.emit('data', this.data) - // Emit detection only if set - if (this.data.detection) - this.emit('detection', this.data.detection) - + if (this.data.detection) { this.emit('detection', this.data.detection) } // Emit geometry only if set - if (this.data.geometry) - this.emit('geometry', this.data.geometry) + if (this.data.geometry) { this.emit('geometry', this.data.geometry) } } catch (e) { this.emit('error', e) } diff --git a/lib/VSSserialClient.js b/lib/VSSserialClient.js index 09b0f84..2ed5820 100644 --- a/lib/VSSserialClient.js +++ b/lib/VSSserialClient.js @@ -1,30 +1,29 @@ const _ = require('lodash') -const chalk = require('chalk') + const dgram = require('dgram') const EventEmitter = require('events') -module.exports = class SerialClient extends EventEmitter{ +module.exports = class SerialClient extends EventEmitter { constructor (options) { super() - this.options = _.defaults(options || {}, { PORT: 5778, HOST: 'localhost' }) - this.PORT = this.options.PORT - this.HOST = this.options.HOST - + this.PORT = this.options.PORT + this.HOST = this.options.HOST this.client = null - } + async ready() {} + async connect (serialPort) { this.client = dgram.createSocket('udp4') } - async send(data) { + async send (data) { this.data = Buffer.from(JSON.stringify(data)) this.client.send(this.data, this.PORT, this.HOST) } diff --git a/lib/Vector.js b/lib/Vector.js index b57984a..634becb 100644 --- a/lib/Vector.js +++ b/lib/Vector.js @@ -1,103 +1,91 @@ -// +// // Vector Utils // -var Vector = {}; +var Vector = {} const PI = Math.PI const TWO_PI = PI * 2 -Vector.sum = function (v1, v2){ - return {x:(v1.x + v2.x), y:(v1.y + v2.y)} +Vector.sum = function (v1, v2) { + return {x: (v1.x + v2.x), y: (v1.y + v2.y)} } -Vector.sub = function (v1, v2){ - return {x:(v1.x - v2.x), y:(v1.y - v2.y)} +Vector.sub = function (v1, v2) { + return {x: (v1.x - v2.x), y: (v1.y - v2.y)} } -Vector.distBetween = function(v1, v2) { - return Math.sqrt(Math.pow(v1.x - v2.x, 2) + Math.pow(v1.y - v2.y, 2)) +Vector.distBetween = function (v1, v2) { + return Math.sqrt(Math.pow(v1.x - v2.x, 2) + Math.pow(v1.y - v2.y, 2)) } // Oposite Vector.mult = function (v1, c) { - return {x:(v1.x * c), y:(v1.y * c)} + return {x: (v1.x * c), y: (v1.y * c)} } // Oposite Vector.div = function (v1, c) { - return { x:(v1.x / c), y:(v1.y / c)} + return {x: (v1.x / c), y: (v1.y / c)} } // Normalize Vector.norm = function (v1) { - var l = Math.sqrt(Math.pow(v1.x, 2) + Math.pow(v1.y, 2)) + var l = Math.sqrt(Math.pow(v1.x, 2) + Math.pow(v1.y, 2)) - if(l == 0.0) - return {x:0,y:0} + if (l === 0.0) { return {x: 0, y: 0} } - return {x:(v1.x / l), y:(v1.y / l)}; + return {x: (v1.x / l), y: (v1.y / l)} } // Create vector from theta -Vector.fromTheta = function (theta){ - return {x:Math.cos(theta), y:Math.sin(theta)} +Vector.fromTheta = function (theta) { + return {x: Math.cos(theta), y: Math.sin(theta)} } -Vector.size = function (v){ - return Math.sqrt(Math.pow(v.x, 2) + Math.pow(v.y, 2)) +Vector.size = function (v) { + return Math.sqrt(Math.pow(v.x, 2) + Math.pow(v.y, 2)) } Vector.angle = function (v) { - return Math.atan2(v.y, v.x); + return Math.atan2(v.y, v.x) } -Vector.angleBetween = function(v1, v2){ - return Vector.normalRelativeAngle(Vector.angle(v2)-Vector.angle(v1)) +Vector.angleBetween = function (v1, v2) { + return Vector.normalRelativeAngle(Vector.angle(v2) - Vector.angle(v1)) } -// Vector.relative = function(a){ -// while(a > 180) a = a - 360; -// while(a < -180) a = a + 360; -// return a -// } - -Vector.direction = function(dir){ - if(dir == "up"){ - return Math.PI / 2 - } - else if(dir == "down"){ - return - Math.PI / 2 - } - else if(dir == "left"){ - return Math.PI - } - else if(dir == "right"){ - return 0 - } +Vector.direction = function (dir) { + if (dir === 'up') { + return Math.PI / 2 + } else if (dir === 'down') { + return -Math.PI / 2 + } else if (dir === 'left') { + return Math.PI + } else if (dir === 'right') { + return 0 + } } Vector.normalRelativeAngle = function (angle) { - return (angle %= TWO_PI) >= 0 ? (angle < PI) ? angle : angle - TWO_PI : (angle >= -PI) ? angle : angle + TWO_PI; + return (angle %= TWO_PI) >= 0 ? (angle < PI) ? angle : angle - TWO_PI : (angle >= -PI) ? angle : angle + TWO_PI } // Normalize Vector.rotate = function (v, theta) { - var currentTheta = Math.atan2(v.y, v.x) - var currentNorm = Math.sqrt(v.x*v.x + v.y*v.y) - - // Creates vector with new Angle - var vect = Vector.fromTheta(currentTheta + theta) - - // Un-normalize vector - return Vector.mult(vect, currentNorm) + var currentTheta = Math.atan2(v.y, v.x) + var currentNorm = Math.sqrt(v.x * v.x + v.y * v.y) + // Creates vector with new Angle + var vect = Vector.fromTheta(currentTheta + theta) + // Un-normalize vector + return Vector.mult(vect, currentNorm) } Vector.toDegrees = function (rads) { - return rads * (180/Math.PI); + return rads * (180 / Math.PI) } Vector.toRadians = function (degs) { - return degs * (Math.PI/180) + return degs * (Math.PI / 180) } -module.exports = Vector; +module.exports = Vector diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..fe8e81d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4480 @@ +{ + "name": "NoPlan", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@serialport/parser-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-1.0.5.tgz", + "integrity": "sha512-GCz/v/KG2Wv7SdQ2nv8jYGBY6D4h5tibj9bs0+pnryCDAr8xmmvnesFW15FIu4rwOMgsKhCHyp7roD8bRGs63A==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "@serialport/parser-cctalk": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-1.0.5.tgz", + "integrity": "sha512-VdoG1rRXb5deHM1c9Akn9djoJuHn030v7owYHEqpJeS6Rs6wrC4Hrkw8NxvV9ZPlMqAJ+5uJCaAUzB1tbVd3rA==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "@serialport/parser-delimiter": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-1.0.5.tgz", + "integrity": "sha512-srDzeNwGM/GjtqK/nFDRIDpcZ6XDgkakFMXBtNDSI+XP6fqO1ynEZok8ljKJxM2ay0CNG83C6/X2xIOHvWhFYQ==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "@serialport/parser-readline": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-1.0.5.tgz", + "integrity": "sha512-QkZoCQPHwdZOMQk7SHz3QSp7xqK4jdNql9M80oXqWt7kNhFvNXguWzf17FfQrPRIb0qiz+96+P6uAOIi02Yxbg==", + "requires": { + "@serialport/parser-delimiter": "^1.0.5", + "safe-buffer": "^5.1.1" + } + }, + "@serialport/parser-ready": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-1.0.5.tgz", + "integrity": "sha512-U/ZkxyY35Z7WrDc0O8TGcGPOdwv6fGVJcZq5vXVko2MRt8wiKVD192mmbfTRZXFAX+rARXtQa3ad3yJzXVhb1g==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "@serialport/parser-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-1.0.5.tgz", + "integrity": "sha512-sX3tRuwwwGV+CZbKEUAKZD/wtG8ZRcGxbiDIm8nyzsPCGv52ck3RlQ9Vp4K8fYjcrGGwm3BWizC4uSzaTLOk1A==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "abs": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/abs/-/abs-1.3.13.tgz", + "integrity": "sha512-VgsJF4AZDoxLwTRx+TlZ6gpHfSaRUcg1Vhyruqxzpr6lTmh3JMO9667AHAVUGHUD3Li9QqjX2WaTXR6pkGFU+Q==", + "requires": { + "ul": "^5.0.0" + } + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-bgblack": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-bgblack/-/ansi-bgblack-0.1.1.tgz", + "integrity": "sha1-poulAHiHcBtqr74/oNrf36juPKI=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-bgblue": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-bgblue/-/ansi-bgblue-0.1.1.tgz", + "integrity": "sha1-Z73ATtybm1J4lp2hlt6j11yMNhM=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-bgcyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-bgcyan/-/ansi-bgcyan-0.1.1.tgz", + "integrity": "sha1-WEiUJWAL3p9VBwaN2Wnr/bUP52g=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-bggreen": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-bggreen/-/ansi-bggreen-0.1.1.tgz", + "integrity": "sha1-TjGRJIUplD9DIelr8THRwTgWr0k=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-bgmagenta": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-bgmagenta/-/ansi-bgmagenta-0.1.1.tgz", + "integrity": "sha1-myhDLAduqpmUGGcqPvvhk5HCx6E=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-bgred": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-bgred/-/ansi-bgred-0.1.1.tgz", + "integrity": "sha1-p2+Sg4OCukMpCmwXeEJPmE1vEEE=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-bgwhite": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-bgwhite/-/ansi-bgwhite-0.1.1.tgz", + "integrity": "sha1-ZQRlE3elim7OzQMxmU5IAljhG6g=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-bgyellow": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-bgyellow/-/ansi-bgyellow-0.1.1.tgz", + "integrity": "sha1-w/4usIzUdmSAKeaHTRWgs49h1E8=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-black": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-black/-/ansi-black-0.1.1.tgz", + "integrity": "sha1-9hheiJNgslRaHsUMC/Bj/EMDJFM=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-blue": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-blue/-/ansi-blue-0.1.1.tgz", + "integrity": "sha1-FbgEmQ6S/JyoxUds6PaZd3wh7b8=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-bold": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-bold/-/ansi-bold-0.1.1.tgz", + "integrity": "sha1-PmOVCvWswq4uZw5vZ96xFdGl9QU=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-colors": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-0.2.0.tgz", + "integrity": "sha1-csMd4qDZoszQysMMyYI+6y9kNLU=", + "requires": { + "ansi-bgblack": "^0.1.1", + "ansi-bgblue": "^0.1.1", + "ansi-bgcyan": "^0.1.1", + "ansi-bggreen": "^0.1.1", + "ansi-bgmagenta": "^0.1.1", + "ansi-bgred": "^0.1.1", + "ansi-bgwhite": "^0.1.1", + "ansi-bgyellow": "^0.1.1", + "ansi-black": "^0.1.1", + "ansi-blue": "^0.1.1", + "ansi-bold": "^0.1.1", + "ansi-cyan": "^0.1.1", + "ansi-dim": "^0.1.1", + "ansi-gray": "^0.1.1", + "ansi-green": "^0.1.1", + "ansi-grey": "^0.1.1", + "ansi-hidden": "^0.1.1", + "ansi-inverse": "^0.1.1", + "ansi-italic": "^0.1.1", + "ansi-magenta": "^0.1.1", + "ansi-red": "^0.1.1", + "ansi-reset": "^0.1.1", + "ansi-strikethrough": "^0.1.1", + "ansi-underline": "^0.1.1", + "ansi-white": "^0.1.1", + "ansi-yellow": "^0.1.1", + "lazy-cache": "^2.0.1" + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-dim": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-dim/-/ansi-dim-0.1.1.tgz", + "integrity": "sha1-QN5MYDqoCG2Oeoa4/5mNXDbu/Ww=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-green": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-green/-/ansi-green-0.1.1.tgz", + "integrity": "sha1-il2al55FjVfEDjNYCzc5C44Q0Pc=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-grey": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-grey/-/ansi-grey-0.1.1.tgz", + "integrity": "sha1-WdmLasK6GfilF5jphT+6eDOaM8E=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-hidden": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-hidden/-/ansi-hidden-0.1.1.tgz", + "integrity": "sha1-7WpMSY0rt8uyidvyqNHcyFZ/rg8=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-inverse": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-inverse/-/ansi-inverse-0.1.1.tgz", + "integrity": "sha1-tq9Fgm/oJr+1KKbHmIV5Q1XM0mk=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-italic": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-italic/-/ansi-italic-0.1.1.tgz", + "integrity": "sha1-EEdDRj9iXBQqA2c5z4XtpoiYbyM=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-magenta": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-magenta/-/ansi-magenta-0.1.1.tgz", + "integrity": "sha1-BjtboW+z8j4c/aKwfAqJ3hHkMK4=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-reset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-reset/-/ansi-reset-0.1.1.tgz", + "integrity": "sha1-5+cSksPH3c1NYu9KbHwFmAkRw7c=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-strikethrough": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-strikethrough/-/ansi-strikethrough-0.1.1.tgz", + "integrity": "sha1-2Eh3FAss/wfRyT685pkE9oiF5Wg=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansi-underline": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-underline/-/ansi-underline-0.1.1.tgz", + "integrity": "sha1-38kg9Ml7WXfqFi34/7mIMIqqcaQ=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-white": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-white/-/ansi-white-0.1.1.tgz", + "integrity": "sha1-nHe3wZPF7pkuYBHTbsTJIbRXiUQ=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, + "ansi-yellow": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-yellow/-/ansi-yellow-0.1.1.tgz", + "integrity": "sha1-y5NW8vRscy8OMZnmEClVp32oPB0=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-swap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arr-swap/-/arr-swap-1.0.1.tgz", + "integrity": "sha1-FHWQ7WX8gVvAf+8Jl8Llgj1kNTQ=", + "requires": { + "is-number": "^3.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "requires": { + "callsite": "1.0.0" + } + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "brfs": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz", + "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==", + "requires": { + "quote-stream": "^1.0.1", + "resolve": "^1.1.5", + "static-module": "^2.2.0", + "through2": "^2.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "choices-separator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/choices-separator/-/choices-separator-2.0.0.tgz", + "integrity": "sha1-kv0XYxgteQM/XFxR0Lo1LlVnxpY=", + "requires": { + "ansi-dim": "^0.1.1", + "debug": "^2.6.6", + "strip-color": "^0.1.0" + } + }, + "chownr": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "clone-deep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-1.0.0.tgz", + "integrity": "sha512-hmJRX8x1QOJVV+GUjOBzi6iauhPqc9hIF6xitWRBbiPZOBb6vGo/mDRIK9P74RTKSQK7AE8B0DDWY/vpRrPmQw==", + "requires": { + "for-own": "^1.0.0", + "is-plain-object": "^2.0.4", + "kind-of": "^5.0.0", + "shallow-clone": "^1.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "deffy": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deffy/-/deffy-2.2.3.tgz", + "integrity": "sha512-c5JD8Z6V1aBWVzn1+aELL97R1pHCwEjXeU3hZXdigkZkxb9vhgFP162kAxGXl992TtAg0btwQyx7d54CqcQaXQ==", + "requires": { + "typpy": "^2.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "draftlog": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/draftlog/-/draftlog-1.0.12.tgz", + "integrity": "sha1-fbajxbYhBrsy3Uo11nvMy2x9naA=" + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "requires": { + "readable-stream": "^2.0.2" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz", + "integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==", + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~6.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-client": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz", + "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "err": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/err/-/err-1.1.1.tgz", + "integrity": "sha1-65KOLhGjFmSPeCgz0PlyWLpDwvg=", + "requires": { + "typpy": "^2.2.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "error-symbol": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/error-symbol/-/error-symbol-0.1.0.tgz", + "integrity": "sha1-Ck2uN9YA0VopukU9jvkg8YRDM/Y=" + }, + "es-abstract": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", + "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + }, + "dependencies": { + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", + "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "eslint": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.6.0.tgz", + "integrity": "sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-escapes": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz", + "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==", + "dev": true, + "requires": { + "type-fest": "^0.5.2" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "figures": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", + "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inquirer": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz", + "integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "string-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz", + "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^5.2.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + } + } + }, + "eslint-config-standard": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz", + "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + } + }, + "eslint-module-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", + "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.11.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-plugin-node": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz", + "integrity": "sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw==", + "dev": true, + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "^5.4.1" + }, + "dependencies": { + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", + "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", + "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", + "dev": true + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "dev": true, + "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + } + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "exec-limiter": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/exec-limiter/-/exec-limiter-3.2.12.tgz", + "integrity": "sha512-2Bj2X3UmPQHIPtYkDW5epEHn1aTtGxP30x8Be6IzXzQzyuavlOdKI4wT56iEt9UUfvI421AHAHHnV+lBIvCcVA==", + "requires": { + "limit-it": "^3.0.0", + "typpy": "^2.1.0" + } + }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + }, + "dependencies": { + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + } + } + }, + "falafel": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", + "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "requires": { + "acorn": "^5.0.0", + "foreach": "^2.0.5", + "isarray": "0.0.1", + "object-keys": "^1.0.6" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "requires": { + "for-in": "^1.0.1" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.name": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/function.name/-/function.name-1.0.12.tgz", + "integrity": "sha512-C7Tu+rAFrWW5RjXqtKtXp2xOdCujq+4i8ZH3w0uz/xrYHBwXZrPt96x8cDAEHrIjeyEv/Jm6iDGyqupbaVQTlw==", + "requires": { + "noop6": "^1.0.1" + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "requires": { + "is-property": "^1.0.0" + } + }, + "git-package-json": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/git-package-json/-/git-package-json-1.4.9.tgz", + "integrity": "sha512-F88a40RBqCS6S7layrE4LIhX5TIVYyUJRYxZjAPPLfCZu9zf0R5B3l3wIY8A7hFb3xAU6Df/AHVMoBQ9SaR1Jw==", + "requires": { + "deffy": "^2.2.1", + "err": "^1.1.1", + "gry": "^5.0.0", + "normalize-package-data": "^2.3.5", + "oargv": "^3.4.1", + "one-by-one": "^3.1.0", + "r-json": "^1.2.1", + "r-package-json": "^1.0.0", + "tmp": "0.0.28" + } + }, + "git-source": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/git-source/-/git-source-1.1.9.tgz", + "integrity": "sha512-LRWKxFrt1lIrEAdRMrCk9sGbEYQdf3TwDe9pEwR8DMau+2dljQjqqwITJqhYIbA0TkFaxatOXzLhBWW89ZMO7w==", + "requires": { + "git-url-parse": "^5.0.1" + } + }, + "git-up": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-1.2.1.tgz", + "integrity": "sha1-JkSAoAax2EJhrB/gmjpRacV+oZ0=", + "requires": { + "is-ssh": "^1.0.0", + "parse-url": "^1.0.0" + } + }, + "git-url-parse": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-5.0.1.tgz", + "integrity": "sha1-/j15xnRq4FBIz6UIyB553du6OEM=", + "requires": { + "git-up": "^1.0.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "glob": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", + "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "got": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", + "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", + "requires": { + "create-error-class": "^3.0.1", + "duplexer2": "^0.1.4", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "node-status-codes": "^1.0.0", + "object-assign": "^4.0.1", + "parse-json": "^2.1.0", + "pinkie-promise": "^2.0.0", + "read-all-stream": "^3.0.0", + "readable-stream": "^2.0.5", + "timed-out": "^3.0.0", + "unzip-response": "^1.0.2", + "url-parse-lax": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "gry": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/gry/-/gry-5.0.8.tgz", + "integrity": "sha512-meq9ZjYVpLzZh3ojhTg7IMad9grGsx6rUUKHLqPnhLXzJkRQvEL2U3tQpS5/WentYTtHtxkT3Ew/mb10D6F6/g==", + "requires": { + "abs": "^1.2.1", + "exec-limiter": "^3.0.0", + "one-by-one": "^3.0.0", + "ul": "^5.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "requires": { + "isarray": "2.0.1" + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hosted-git-info": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "info-symbol": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/info-symbol/-/info-symbol-0.1.0.tgz", + "integrity": "sha1-J4QdcoZ920JCzWEtecEGM4gcang=" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", + "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" + }, + "is-ssh": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", + "integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==", + "requires": { + "protocols": "^1.1.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "iterate-object": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/iterate-object/-/iterate-object-1.3.3.tgz", + "integrity": "sha512-DximWbkke36cnrSfNJv6bgcB2QOMV9PRD2FiowwzCoMsh8RupFLdbNIzWe+cVDWT+NIMNJgGlB1dGxP6kpzGtA==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "koalas": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/koalas/-/koalas-1.0.2.tgz", + "integrity": "sha1-MYQz8HQjXbePrlZhoCqMpT7ilc0=" + }, + "lazy-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", + "requires": { + "set-getter": "^0.1.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "limit-it": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/limit-it/-/limit-it-3.2.9.tgz", + "integrity": "sha512-3cAf+D47VdMrrzLpV3wIyEHoAACc7FonHMz+I8onocXdnWD2zBeicse851NZ9TUeCEyuBM35Cx82mpdx1WLm2A==", + "requires": { + "typpy": "^2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "log-ok": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/log-ok/-/log-ok-0.1.1.tgz", + "integrity": "sha1-vqPdNqzQuKckDXhza1uXxlREozQ=", + "requires": { + "ansi-green": "^0.1.1", + "success-symbol": "^0.1.0" + } + }, + "log-utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/log-utils/-/log-utils-0.2.1.tgz", + "integrity": "sha1-pMIXoN2aUFFdm5ICBgkas9TgMc8=", + "requires": { + "ansi-colors": "^0.2.0", + "error-symbol": "^0.1.0", + "info-symbol": "^0.1.0", + "log-ok": "^0.1.1", + "success-symbol": "^0.1.0", + "time-stamp": "^1.0.1", + "warning-symbol": "^0.1.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "magic-string": { + "version": "0.22.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", + "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", + "requires": { + "vlq": "^0.2.2" + } + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge-source-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", + "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", + "requires": { + "source-map": "^0.5.6" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=" + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "nan": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==" + }, + "napi-build-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.1.tgz", + "integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-abi": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.12.0.tgz", + "integrity": "sha512-VhPBXCIcvmo/5K8HPmnWJyyhvgKxnHTUMXR/XwGHV68+wrgkzST4UmQrY/XszSWA5dtnXpNp528zkcyJ/pzVcw==", + "requires": { + "semver": "^5.4.1" + } + }, + "node-gamepad": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/node-gamepad/-/node-gamepad-0.1.15.tgz", + "integrity": "sha1-yZtZn7Tdh0b8ThWZB+xeHB6AFsA=", + "requires": { + "colors": "^0.6.2", + "node-hid": ">= 0.3.1" + } + }, + "node-hid": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.7.9.tgz", + "integrity": "sha512-vJnonTqmq3frCyTumJqG4g2IZcny3ynkfmbfDfQ90P3ZhRzcWYS/Um1ux6HFmAxmkaQnrZqIYHcGpL7kdqY8jA==", + "requires": { + "bindings": "^1.5.0", + "nan": "^2.13.2", + "prebuild-install": "^5.3.0" + }, + "dependencies": { + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz", + "integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==", + "requires": { + "readable-stream": "^3.0.1" + } + }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "requires": { + "mimic-response": "^2.0.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "mimic-response": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.0.0.tgz", + "integrity": "sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ==" + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + }, + "prebuild-install": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.2.tgz", + "integrity": "sha512-INDfXzTPnhT+WYQemqnAXlP7SvfiFMopMozSgXCZ+RDLb279gKfIuLk4o7PgEawLp3WrMgIYGBpkxpraROHsSA==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "tar-fs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz", + "integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==", + "requires": { + "chownr": "^1.1.1", + "mkdirp": "^0.5.1", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "tar-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.0.tgz", + "integrity": "sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==", + "requires": { + "bl": "^3.0.0", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + } + } + }, + "node-status-codes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=" + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "noop6": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/noop6/-/noop6-1.0.8.tgz", + "integrity": "sha512-+Al5csMVc40I8xRfJsyBcN1IbpyvebOuQmMfxdw+AL6ECELey12ANgNTRhMfTwNIDU4W9W0g8EHLcsb3+3qPFA==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oargv": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/oargv/-/oargv-3.4.9.tgz", + "integrity": "sha512-24Eatdf7OGezTAU0Yw3HaoO9x+GTFnmBkuFHfWEQtVsIKbD7VMHhyIlDMtxxUxfZKPBPHYsTo8UgGwKr4ySewA==", + "requires": { + "iterate-object": "^1.1.0", + "ul": "^5.0.0" + } + }, + "obj-def": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/obj-def/-/obj-def-1.0.7.tgz", + "integrity": "sha512-ahx1PnGDpovRglgczxsKtoYhPhrhYEG1rs3WklAHMTk29DyStqsrGDVISOIGZLF+ewK4m5CFZNuZXIXRQwZUMg==", + "requires": { + "deffy": "^2.2.2" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + } + } + }, + "object-inspect": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz", + "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "one-by-one": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/one-by-one/-/one-by-one-3.2.7.tgz", + "integrity": "sha512-EFE5hyHMGPcesACi1tT6HRmMK23Q74ujX2gjhfGD9qMkz7CxD1AJd5TmBHIEEzuL7h7hKwWh9n9hJ5ClQJnO/Q==", + "requires": { + "obj-def": "^1.0.0", + "sliced": "^1.0.1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "package-json": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz", + "integrity": "sha1-DRW9Z9HLvduyyiIv8u24a8sxqLs=", + "requires": { + "got": "^5.0.0", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "package-json-path": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/package-json-path/-/package-json-path-1.0.8.tgz", + "integrity": "sha512-8OCXvm2TmEYoWC7e9AswLC0eoKY3RGbkupbiWa2vaTFaH4vEE3Kr+oeefLVm/7N4me2gYh5SjQYsdwAZLkL87g==", + "requires": { + "abs": "^1.2.1" + } + }, + "package.json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/package.json/-/package.json-2.0.1.tgz", + "integrity": "sha1-+IYFnSpJ7QduZIg2ldc7K0bSHW0=", + "requires": { + "git-package-json": "^1.4.0", + "git-source": "^1.1.0", + "package-json": "^2.3.1" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-url": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", + "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", + "requires": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" + } + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "pointer-symbol": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pointer-symbol/-/pointer-symbol-1.0.0.tgz", + "integrity": "sha1-YPkRAgTqepKbYmRKITFVQ8uz1Ec=" + }, + "prebuild-install": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-4.0.0.tgz", + "integrity": "sha512-7tayxeYboJX0RbVzdnKyGl2vhQRWr6qfClEXDhOkXjuaOKCw2q8aiuFhONRYVsG/czia7KhpykIlI2S2VaPunA==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^1.0.2", + "github-from-package": "0.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "node-abi": "^2.2.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "os-homedir": "^1.0.1", + "pump": "^2.0.1", + "rc": "^1.1.6", + "simple-get": "^2.7.0", + "tar-fs": "^1.13.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promirepl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promirepl/-/promirepl-1.0.1.tgz", + "integrity": "sha1-KVGq66K/P+InT/Y6FtlMBMpghy4=" + }, + "prompt-actions": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/prompt-actions/-/prompt-actions-3.0.2.tgz", + "integrity": "sha512-dhz2Fl7vK+LPpmnQ/S/eSut4BnH4NZDLyddHKi5uTU/2PDn3grEMGkgsll16V5RpVUh/yxdiam0xsM0RD4xvtg==", + "requires": { + "debug": "^2.6.8" + } + }, + "prompt-base": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/prompt-base/-/prompt-base-4.1.0.tgz", + "integrity": "sha512-svGzgLUKZoqomz9SGMkf1hBG8Wl3K7JGuRCXc/Pv7xw8239hhaTBXrmjt7EXA9P/QZzdyT8uNWt9F/iJTXq75g==", + "requires": { + "component-emitter": "^1.2.1", + "debug": "^3.0.1", + "koalas": "^1.0.2", + "log-utils": "^0.2.1", + "prompt-actions": "^3.0.2", + "prompt-question": "^5.0.1", + "readline-ui": "^2.2.3", + "readline-utils": "^2.2.3", + "static-extend": "^0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "prompt-checkbox": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/prompt-checkbox/-/prompt-checkbox-2.2.0.tgz", + "integrity": "sha512-T/QWgkdUmKjRSr0FQlV8O+LfgmBk8PwDbWhzllm7mwWNAjs3qOVuru5Y1gV4/14L73zCncqcuwGwvnDyVcVgvA==", + "requires": { + "ansi-cyan": "^0.1.1", + "debug": "^2.6.8", + "prompt-base": "^4.0.2" + } + }, + "prompt-choices": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/prompt-choices/-/prompt-choices-4.1.0.tgz", + "integrity": "sha512-ZNYLv6rW9z9n0WdwCkEuS+w5nUAGzRgtRt6GQ5aFNFz6MIcU7nHFlHOwZtzy7RQBk80KzUGPSRQphvMiQzB8pg==", + "requires": { + "arr-flatten": "^1.1.0", + "arr-swap": "^1.0.1", + "choices-separator": "^2.0.0", + "clone-deep": "^4.0.0", + "collection-visit": "^1.0.0", + "define-property": "^2.0.2", + "is-number": "^6.0.0", + "kind-of": "^6.0.2", + "koalas": "^1.0.2", + "log-utils": "^0.2.1", + "pointer-symbol": "^1.0.0", + "radio-symbol": "^2.0.0", + "set-value": "^3.0.0", + "strip-color": "^0.1.0", + "terminal-paginator": "^2.0.2", + "toggle-array": "^1.0.1" + }, + "dependencies": { + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "requires": { + "kind-of": "^6.0.2" + } + } + } + }, + "prompt-list": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/prompt-list/-/prompt-list-3.2.0.tgz", + "integrity": "sha512-PDao47cmC9+m2zEUghH+WIIascd8SuyyWO+akuUubd0XxOQyUH96HMdIcL3YnNS8kJUHwddH1rHVgL9vZA1QsQ==", + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-dim": "^0.1.1", + "prompt-radio": "^1.2.1" + } + }, + "prompt-question": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/prompt-question/-/prompt-question-5.0.2.tgz", + "integrity": "sha512-wreaLbbu8f5+7zXds199uiT11Ojp59Z4iBi6hONlSLtsKGTvL2UY8VglcxQ3t/X4qWIxsNCg6aT4O8keO65v6Q==", + "requires": { + "clone-deep": "^1.0.0", + "debug": "^3.0.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "kind-of": "^5.0.2", + "koalas": "^1.0.2", + "prompt-choices": "^4.0.5" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "prompt-radio": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prompt-radio/-/prompt-radio-1.2.1.tgz", + "integrity": "sha512-vH1iAkgbWyvZBC1BTajydiHmwJP4F1b684gq0fm2wOjPVW1zaDo01OXWr/Dske0XdoHhtZFNMOXNj/ZUSRBywg==", + "requires": { + "debug": "^2.6.8", + "prompt-checkbox": "^2.2.0" + } + }, + "protocol-buffers": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/protocol-buffers/-/protocol-buffers-3.2.1.tgz", + "integrity": "sha1-NyWOF+JKCC8G67F3MekoUdHHaIk=", + "requires": { + "brfs": "^1.4.0", + "generate-function": "^2.0.0", + "generate-object-property": "^1.2.0", + "protocol-buffers-schema": "^3.1.1", + "signed-varint": "^2.0.0", + "varint": "^5.0.0" + } + }, + "protocol-buffers-schema": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz", + "integrity": "sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w==" + }, + "protocols": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.7.tgz", + "integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==" + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "quote-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", + "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", + "requires": { + "buffer-equal": "0.0.1", + "minimist": "^1.1.3", + "through2": "^2.0.0" + } + }, + "r-json": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/r-json/-/r-json-1.2.9.tgz", + "integrity": "sha512-E5u25XBE7PpZmH5XwtthAmNvSLMTygDQMpcPtCTUBdvwPaqgIYJrxlRQJhG55Sgz7uC0Tuyh5nqNrsDT3uiefA==" + }, + "r-package-json": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/r-package-json/-/r-package-json-1.0.8.tgz", + "integrity": "sha512-y+dKPLBYKcNMY8pNy+m8YLUqeGsEhhOu0wrqfu1yr8yGX+08CzMq2uUV5GSkGA21GcaIyt6lQAiSoD+DFf3/ag==", + "requires": { + "package-json-path": "^1.0.0", + "r-json": "^1.2.1" + } + }, + "radio-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/radio-symbol/-/radio-symbol-2.0.0.tgz", + "integrity": "sha1-eqm/xQSFY21S3XbWqOYxspB5muE=", + "requires": { + "ansi-gray": "^0.1.1", + "ansi-green": "^0.1.1", + "is-windows": "^1.0.1" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "read-all-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", + "requires": { + "pinkie-promise": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + } + } + }, + "readline-ui": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/readline-ui/-/readline-ui-2.2.3.tgz", + "integrity": "sha512-ix7jz0PxqQqcIuq3yQTHv1TOhlD2IHO74aNO+lSuXsRYm1d+pdyup1yF3zKyLK1wWZrVNGjkzw5tUegO2IDy+A==", + "requires": { + "component-emitter": "^1.2.1", + "debug": "^2.6.8", + "readline-utils": "^2.2.1", + "string-width": "^2.0.0" + } + }, + "readline-utils": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/readline-utils/-/readline-utils-2.2.3.tgz", + "integrity": "sha1-b4R9a48ZFcORtYHDZ81HhzhiNRo=", + "requires": { + "arr-flatten": "^1.1.0", + "extend-shallow": "^2.0.1", + "is-buffer": "^1.1.5", + "is-number": "^3.0.0", + "is-windows": "^1.0.1", + "koalas": "^1.0.2", + "mute-stream": "0.0.7", + "strip-color": "^0.1.0", + "window-size": "^1.1.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "registry-auth-token": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "requires": { + "rc": "^1.0.1" + } + }, + "require-smart": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/require-smart/-/require-smart-1.1.2.tgz", + "integrity": "sha1-fxikPSyqqOiWoBUklVti9EN/pD8=" + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "^2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "requires": { + "rx-lite": "*" + } + }, + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "serialport": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-6.2.2.tgz", + "integrity": "sha512-BQqTR06ZXKwKB6rUjeANm3aIZo0rqNbQsrQX5zKEDcNY4rxiu5dvdcfIOaAGuZkhW7jAKJsgKC5TjeURtLVuOQ==", + "requires": { + "@serialport/parser-byte-length": "^1.0.5", + "@serialport/parser-cctalk": "^1.0.5", + "@serialport/parser-delimiter": "^1.0.5", + "@serialport/parser-readline": "^1.0.5", + "@serialport/parser-ready": "^1.0.5", + "@serialport/parser-regex": "^1.0.5", + "bindings": "1.3.0", + "commander": "^2.13.0", + "debug": "^3.1.0", + "nan": "^2.9.2", + "prebuild-install": "^4.0.0", + "promirepl": "^1.0.1", + "prompt-list": "^3.2.0", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "serve-favicon": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", + "integrity": "sha1-k10kDN/g9YBTB/3+ln2IlCosvPA=", + "requires": { + "etag": "~1.8.1", + "fresh": "0.5.2", + "ms": "2.1.1", + "parseurl": "~1.3.2", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-getter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", + "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", + "requires": { + "to-object-path": "^0.3.0" + } + }, + "set-value": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-3.0.1.tgz", + "integrity": "sha512-w6n3GUPYAWQj4ZyHWzD7K2FnFXHx9OTwJYbWg+6nXjG8sCLfs9DGv+KlqglKIIJx+ks7MlFuwFW2RBPb+8V+xg==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "shallow-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "signed-varint": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/signed-varint/-/signed-varint-2.0.1.tgz", + "integrity": "sha1-UKmYnafJjCxh2tEZvJdHDvhSgSk=", + "requires": { + "varint": "~5.0.0" + } + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + }, + "socket.io": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz", + "integrity": "sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==", + "requires": { + "debug": "~4.1.0", + "engine.io": "~3.3.1", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.2.0", + "socket.io-parser": "~3.3.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" + }, + "socket.io-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", + "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.3.1", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", + "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "ssl-vision": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ssl-vision/-/ssl-vision-1.0.2.tgz", + "integrity": "sha512-WcIn0jAgCwWEctQGa1MkfezRhPfRdpl8FjIKGKp0gKRlll6MHVSO0G+r+SnLP2xH+Uf+Ib89/lY7iqPCwHOYZQ==", + "requires": { + "protocol-buffers": "^3.2.1" + } + }, + "static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "requires": { + "escodegen": "^1.8.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "static-module": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.2.5.tgz", + "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==", + "requires": { + "concat-stream": "~1.6.0", + "convert-source-map": "^1.5.1", + "duplexer2": "~0.1.4", + "escodegen": "~1.9.0", + "falafel": "^2.1.0", + "has": "^1.0.1", + "magic-string": "^0.22.4", + "merge-source-map": "1.0.4", + "object-inspect": "~1.4.0", + "quote-stream": "~1.0.2", + "readable-stream": "~2.3.3", + "shallow-copy": "~0.0.1", + "static-eval": "^2.0.0", + "through2": "~2.0.3" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-color": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", + "integrity": "sha1-EG9l09PmotlAHKwOsM6LinArT3s=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "success-symbol": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/success-symbol/-/success-symbol-0.1.0.tgz", + "integrity": "sha1-JAIuSG878c3KCUKDt2nEctO3KJc=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "terminal-paginator": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/terminal-paginator/-/terminal-paginator-2.0.2.tgz", + "integrity": "sha512-IZMT5ECF9p4s+sNCV8uvZSW9E1+9zy9Ji9xz2oee8Jfo7hUFpauyjxkhfRcIH6Lu3Wdepv5D1kVRc8Hx74/LfQ==", + "requires": { + "debug": "^2.6.6", + "extend-shallow": "^2.0.1", + "log-utils": "^0.2.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" + }, + "timed-out": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", + "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=" + }, + "tmp": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz", + "integrity": "sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA=", + "requires": { + "os-tmpdir": "~1.0.1" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "toggle-array": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toggle-array/-/toggle-array-1.0.1.tgz", + "integrity": "sha1-y/WEB5K9UJfzMReugkyTKv/ofVg=", + "requires": { + "isobject": "^3.0.0" + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", + "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "dependencies": { + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + } + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typpy": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/typpy/-/typpy-2.3.11.tgz", + "integrity": "sha512-Jh/fykZSaxeKO0ceMAs6agki9T5TNA9kiIR6fzKbvafKpIw8UlNlHhzuqKyi5lfJJ5VojJOx9tooIbyy7vHV/g==", + "requires": { + "function.name": "^1.0.3" + } + }, + "ul": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/ul/-/ul-5.2.14.tgz", + "integrity": "sha512-VaIRQZ5nkEd8VtI3OYo5qNbhHQuBtPtu5k5GrYaKCmcP1H+FkuWtS+XFTSU1oz5GiuAg2FJL5ka8ufr9zdm8eg==", + "requires": { + "deffy": "^2.2.2", + "typpy": "^2.3.4" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unzip-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "^1.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "varint": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.0.tgz", + "integrity": "sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==" + }, + "warning-symbol": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/warning-symbol/-/warning-symbol-0.1.0.tgz", + "integrity": "sha1-uzHdEbeg+dZ6su2V9Fe2WCW7rSE=" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "window-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-1.1.1.tgz", + "integrity": "sha512-5D/9vujkmVQ7pSmc0SCBmHXbkv6eaHwXEx65MywhmUMsI8sGqJ972APq1lotfcwMKPFLuCFfL8xGHLIp7jaBmA==", + "requires": { + "define-property": "^1.0.0", + "is-number": "^3.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + } + } +} diff --git a/package.json b/package.json index 06b677f..b6ddfc7 100644 --- a/package.json +++ b/package.json @@ -21,5 +21,13 @@ "serve-favicon": "^2.4.5", "socket.io": "^2.1.1", "ssl-vision": "^1.0.2" + }, + "devDependencies": { + "eslint": "^6.6.0", + "eslint-config-standard": "^11.0.0", + "eslint-plugin-import": "^2.11.0", + "eslint-plugin-node": "^6.0.1", + "eslint-plugin-promise": "^3.7.0", + "eslint-plugin-standard": "^3.0.1" } } diff --git a/players/Attacker.js b/players/Attacker.js index b971cc3..5767509 100644 --- a/players/Attacker.js +++ b/players/Attacker.js @@ -4,20 +4,18 @@ const Intention = require('../Intention') const IntentionPlayer = require('./IntentionPlayer') const LineIntention = require('../Intention/LineIntention') const PointIntention = require('../Intention/PointIntention') -const LookAtIntention = require('../Intention/LookAtIntention') -// const FORWARD_SPEED = 500 // ~4.3s -const FORWARD_SPEED = 500 // ~4.3s - -const ANGULAR_MULTIPLIER = 10 +const AvoidWallDecay = TensorMath.new.mult(-1).sum(1).finish +const AvoidWallSpeed = 100 +const AvoidWallCorridor = 200 +const OffsetBallDistance = 75 const Direction = { UP: Math.PI / 2, - DOWN: - Math.PI / 2, + DOWN: -(Math.PI / 2), RIGHT: 0, - LEFT: Math.PI, + LEFT: Math.PI } - const Field = { width: 1700, TopLeft: {x: -775, y: 675}, @@ -26,247 +24,131 @@ const Field = { BottomRight: {x: 775, y: -675} } -const AvoidWall_Decay = TensorMath.new.mult(-1).sum(1).finish -const AvoidWall_Speed = 100 -const AvoidWall_Corridor = 200 - -const OffsetBallDistance = 75 -const MinAttackSpeed = 150 - module.exports = class Attacker extends IntentionPlayer { - setup(){ - - let ball = () => this.ball + setup () { + const ball = this.ball this.orientation = Math.PI / 2 this.position = {x: 0, y: 40} - // this.$goGoalUp = new Intention('goGoalUp') - // this.$goGoalUp.addIntetion(new LineIntention('goal', { - // // target: ball, - // target: {x: 700, y: 0}, - // lineDist:200, - // lineDistMax:650, - // lineSize:false, - // theta:Math.PI/2, - // decay: TensorMath.new.mult(-1).finish, - // multiplier: FORWARD_SPEED, - // })) - - // ============================================== Avoid Robots + // Avoid Robots this.$avoidRobots = new Intention('avoidRobots') this.addIntetion(this.$avoidRobots) - // for (let i = 0; i < 3; i ++) { - // this.$avoidRobots.addIntetion(new PointIntention('avoidRobot#'+i, { - // // target: ball, - // target: (), - // theta: Direction.RIGHT, - // lineSize: Field.width, // Largura do segmento de reta - // lineSizeSingleSide: true, - - // lineDist: 300, // Tamanho da repelência - // lineDistMax: 300, // Tamanho da repelência - // lineDistSingleSide: true, - - // decay: TensorMath.new.mult(-1).finish, - // multiplier: 300, - // })) - // } - - - // ============================================== Avoid Walls + // Avoid Walls this.$avoidWalls = new Intention('avoidWalls') this.addIntetion(this.$avoidWalls) this.$avoidWalls.addIntetion(new LineIntention('topWall', { - // target: ball, target: Field.TopLeft, theta: Direction.RIGHT, - lineSize: Field.width, // Largura do segmento de reta - // lineSizeSingleSide: true, - - lineDist: AvoidWall_Corridor, // Tamanho da repelência - lineDistMax: AvoidWall_Corridor, // Tamanho da repelência - // lineDistSingleSide: true, - - decay: AvoidWall_Decay, - multiplier: AvoidWall_Speed, + lineSize: Field.width, + lineDist: AvoidWallCorridor, + lineDistMax: AvoidWallCorridor, + decay: AvoidWallDecay, + multiplier: AvoidWallSpeed })) - this.$avoidWalls.addIntetion(new LineIntention('bottomWall', { - // target: ball, target: Field.BottomRight, theta: Direction.LEFT, - lineSize: Field.width, // Largura do segmento de reta - // lineSizeSingleSide: true, - - lineDist: AvoidWall_Corridor, // Tamanho da repelência - lineDistMax: AvoidWall_Corridor, // Tamanho da repelência - // lineDistSingleSide: true, - - decay: AvoidWall_Decay, - multiplier: AvoidWall_Speed, + lineSize: Field.width, + lineDist: AvoidWallCorridor, + lineDistMax: AvoidWallCorridor, + decay: AvoidWallDecay, + multiplier: AvoidWallSpeed })) - // ============================================== Prepare Attack + // Prepare Attack this.$prepareAttack = new Intention('prepareAttack') this.addIntetion(this.$prepareAttack) this.$prepareAttack.addIntetion(new LineIntention('avoidBallOwnGoal', { target: ball, theta: Direction.DOWN, - lineSize: 50, // Largura do segmento de reta - lineDist: 180, // Tamanho da repelência - lineDistMax: 180, // Tamanho da repelência + lineSize: 50, + lineDist: 180, + lineDistMax: 180, lineDistSingleSide: true, decay: TensorMath.new.mult(-1).sum(1).finish, - multiplier: 700, + multiplier: 700 })) this.$prepareAttack.addIntetion(new LineIntention('openBallSpaceFromOtherSide', { target: ball, theta: Direction.RIGHT, - lineSize: 350, // Largura do segmento de reta + lineSize: 350, lineSizeSingleSide: true, - lineDist: 250, // Tamanho da repelência - lineDistMax: 250, // Tamanho da repelência + lineDist: 250, + lineDistMax: 250, decay: TensorMath.new.mult(-1).sum(1).finish, - multiplier: 600, + multiplier: 600 })) this.$prepareAttack.addIntetion(new PointIntention('followBall', { target: () => { - return {x: this.ball.x - OffsetBallDistance, y: this.ball.y} + return {x: this.ball.x - OffsetBallDistance, y: this.ball.y} }, radius: 150, radiusMax: false, decay: TensorMath.new.finish, - multiplier: 700, + multiplier: 700 })) - // ============================================== Rules + // Rules this.$rules = new LineIntention('avoid_defence_fault', { - target: {x: -850 , y: 0}, + target: {x: -850, y: 0}, theta: Direction.UP, - lineSize: 100000, //360, + lineSize: 100000, lineDist: 650, lineDistMax: 650, decay: TensorMath.new.mult(-1).sum(1).finish, - multiplier: 2200, + multiplier: 2200 }) this.addIntetion(this.$rules) - // ============================================== Attack with Acceleration - // this.$attackAccelerated = new Intention('attackAccelerated') - // this.addIntetion(this.$attackAccelerated) - this.$attackAccelerated = this.addIntetion(new PointIntention('goBall', { target: () => { - - // let prop = Vector.size(Vector.sub(this.ball, this.position)) - // if (prop < 100) { - // return {x: 800, y: 0} - // } - // console.log('dist', prop.toFixed(0)) - return {x: this.ball.x, y: this.ball.y} + return {x: this.ball.x, y: this.ball.y} }, radius: OffsetBallDistance + 150, radiusMax: OffsetBallDistance + 150, decay: TensorMath.new.constant(1).finish, - multiplier: this.currentAttackMultiplier.bind(this), + multiplier: this.currentAttackMultiplier.bind(this) })) this.$goGoal = this.addIntetion(new PointIntention('goGoal', { target: {x: 800, y: 30}, - // () => { - // // let prop = Vector.size(Vector.sub(this.ball, this.position)) - // // if (prop < 100) { - // return {x: 800, y: 0} - // // } - // // console.log('dist', prop.toFixed(0)) - // // return {x: this.ball.x, y: this.ball.y} - // }, radius: 150, radiusMax: false, decay: TensorMath.new.finish, - multiplier: 800, + multiplier: 800 })) - - // this.$goGoal = this.addIntetion(new LineIntention('goGoal', { - // target: {x: 900, y: 0}, - // theta: Direction.LEFT, - - // lineSize: 100000, //360, - // lineDist: 650, - // lineDistMax: 650, - // decay: TensorMath.new.mult(-1).sum(1).finish, - // multiplier: 800, - // // () => { - // // // let prop = Vector.size(Vector.sub(this.ball, this.position)) - // // // if (prop < 100) { - // // return {x: 800, y: 0} - // // // } - // // // console.log('dist', prop.toFixed(0)) - // // // return {x: this.ball.x, y: this.ball.y} - // // }, - // // radius: 150, - // // radiusMax: false, - // // decay: TensorMath.new.finish, - // // multiplier: 600, - // })) - } - currentAttackMultiplier(dist) { - // this.$prepareAttack.weight = 0 - - let speed = Math.max(260, Vector.size(this.ballSpeed)*2.0 + 260) - // console.log('speed', speed.toFixed(0)) + currentAttackMultiplier () { + let speed = Math.max(260, Vector.size(this.ballSpeed) * 2.0 + 260) return speed } - loop () { let toBall = Vector.sub({x: this.ball.x, y: this.ball.y}, this.position) let toBallDist = Vector.size(toBall) let toBallAngle = Vector.toDegrees(Vector.angle(toBall)) let withinAttackArea = (toBall.x > 0) && Math.abs(toBallAngle) < (35) // 35 - + if (!withinAttackArea) { this.$prepareAttack.weight = 1 this.$attackAccelerated.weight = 0 this.$goGoal.weight = 0 - // console.log('outside', (toBallAngle).toFixed(0)) } else { this.$prepareAttack.weight = 0.5 this.$attackAccelerated.weight = 1 - if (toBallDist > 300 || (toBallDist < 120 && this.ballSpeed.x > 300)) { - console.log('inside GO GOAL!', toBallDist.toFixed(0) + '\t'+this.ballSpeed.x.toFixed(0)) this.$goGoal.weight = 1 } else { - console.log('inside ', toBallDist.toFixed(0) + '\t'+this.ballSpeed.x.toFixed(0)) this.$goGoal.weight = 0 } -// >>>>>>> Stashed changes + this.$avoidWalls.weight = 0.3 } - - // this.$prepareAttack.weight = 0 - - // let speed = Math.max(160, Vector.size(this.ballSpeed) + 70) * 2 - // console.log('speed', speed.toFixed(0)) - // return speed - -// <<<<<<< Updated upstream -// this.$avoidWalls.weight = 1 -// console.log(this.getIntentionsInfo()) -// ======= - - this.$avoidWalls.weight = 0.3 -// >>>>>>> Stashed changes - // this.$prepareAttack.weight = 1 - // this.$attackAccelerated.weight = 1 - // console.log(this.intentionGroup.output) } -} \ No newline at end of file +} diff --git a/players/Attacker2.js b/players/Attacker2.js index 1d0b9ba..94ee610 100644 --- a/players/Attacker2.js +++ b/players/Attacker2.js @@ -4,20 +4,13 @@ const Intention = require('../Intention') const IntentionPlayer = require('./IntentionPlayer') const LineIntention = require('../Intention/LineIntention') const PointIntention = require('../Intention/PointIntention') -const LookAtIntention = require('../Intention/LookAtIntention') - -// const FORWARD_SPEED = 500 // ~4.3s -const FORWARD_SPEED = 500 // ~4.3s - -const ANGULAR_MULTIPLIER = 10 const Direction = { UP: Math.PI / 2, - DOWN: - Math.PI / 2, + DOWN: -(Math.PI / 2), RIGHT: 0, - LEFT: Math.PI, + LEFT: Math.PI } - const Field = { width: 1700, TopLeft: {x: -775, y: 675}, @@ -26,258 +19,146 @@ const Field = { BottomRight: {x: 775, y: -675} } -const AvoidWall_Decay = TensorMath.new.mult(-1).sum(1).finish -const AvoidWall_Speed = 100 -const AvoidWall_Corridor = 200 - +const AvoidWallDecay = TensorMath.new.mult(-1).sum(1).finish +const AvoidWallSpeed = 100 +const AvoidWallCorridor = 200 const OffsetBallDistance = 75 -const MinAttackSpeed = 150 module.exports = class Attacker2 extends IntentionPlayer { - setup(){ - - let ball = () => this.ball - + setup () { + const ball = this.ball this.orientation = Math.PI / 2 this.position = {x: 0, y: 40} - // this.$goGoalUp = new Intention('goGoalUp') - // this.$goGoalUp.addIntetion(new LineIntention('goal', { - // // target: ball, - // target: {x: 700, y: 0}, - // lineDist:200, - // lineDistMax:650, - // lineSize:false, - // theta:Math.PI/2, - // decay: TensorMath.new.mult(-1).finish, - // multiplier: FORWARD_SPEED, - // })) - - // ============================================== Avoid Robots + // Avoid Robots this.$avoidRobots = new Intention('avoidRobots') this.addIntetion(this.$avoidRobots) - // for (let i = 0; i < 3; i ++) { - // this.$avoidRobots.addIntetion(new PointIntention('avoidRobot#'+i, { - // // target: ball, - // target: (), - // theta: Direction.RIGHT, - // lineSize: Field.width, // Largura do segmento de reta - // lineSizeSingleSide: true, - - // lineDist: 300, // Tamanho da repelência - // lineDistMax: 300, // Tamanho da repelência - // lineDistSingleSide: true, - - // decay: TensorMath.new.mult(-1).finish, - // multiplier: 300, - // })) - // } - - - // ============================================== Avoid Walls + // Avoid Walls this.$avoidWalls = new Intention('avoidWalls') this.addIntetion(this.$avoidWalls) - this.$avoidWalls.addIntetion(new LineIntention('topWall', { - // target: ball, target: Field.TopLeft, theta: Direction.RIGHT, - lineSize: Field.width, // Largura do segmento de reta - // lineSizeSingleSide: true, - - lineDist: AvoidWall_Corridor, // Tamanho da repelência - lineDistMax: AvoidWall_Corridor, // Tamanho da repelência - // lineDistSingleSide: true, - - decay: AvoidWall_Decay, - multiplier: AvoidWall_Speed, + lineSize: Field.width, + lineDist: AvoidWallCorridor, + lineDistMax: AvoidWallCorridor, + decay: AvoidWallDecay, + multiplier: AvoidWallSpeed })) this.$avoidWalls.addIntetion(new LineIntention('bottomWall', { - // target: ball, target: Field.BottomRight, theta: Direction.LEFT, - lineSize: Field.width, // Largura do segmento de reta - // lineSizeSingleSide: true, - - lineDist: AvoidWall_Corridor, // Tamanho da repelência - lineDistMax: AvoidWall_Corridor, // Tamanho da repelência - // lineDistSingleSide: true, - - decay: AvoidWall_Decay, - multiplier: AvoidWall_Speed, + lineSize: Field.width, + lineDist: AvoidWallCorridor, + lineDistMax: AvoidWallCorridor, + decay: AvoidWallDecay, + multiplier: AvoidWallSpeed })) - // ============================================== Prepare Attack + // Prepare Attack this.$prepareAttack = new Intention('prepareAttack') this.addIntetion(this.$prepareAttack) - this.$prepareAttack.addIntetion(new LineIntention('avoidBallOwnGoal', { target: ball, theta: Direction.DOWN, - lineSize: 50, // Largura do segmento de reta - lineDist: 180, // Tamanho da repelência - lineDistMax: 180, // Tamanho da repelência + lineSize: 50, + lineDist: 180, + lineDistMax: 180, lineDistSingleSide: true, decay: TensorMath.new.mult(-1).sum(1).finish, - multiplier: 500, + multiplier: 500 })) - this.$prepareAttack.addIntetion(new LineIntention('openBallSpaceFromOtherSide', { target: ball, theta: Direction.RIGHT, - lineSize: 350, // Largura do segmento de reta + lineSize: 350, lineSizeSingleSide: true, - lineDist: 250, // Tamanho da repelência - lineDistMax: 250, // Tamanho da repelência + lineDist: 250, + lineDistMax: 250, decay: TensorMath.new.mult(-1).sum(1).finish, - multiplier: 400, + multiplier: 400 })) this.$prepareAttack.addIntetion(new PointIntention('followBall', { target: () => { - return {x: this.ball.x - OffsetBallDistance, y: this.ball.y} + return {x: this.ball.x - OffsetBallDistance, y: this.ball.y} }, radius: 150, radiusMax: false, decay: TensorMath.new.finish, - multiplier: 500, + multiplier: 500 })) - // ============================================== Rules + // Rules this.$rules = new LineIntention('avoid_defence_fault', { - target: {x: -850 , y: 0}, + target: {x: -850, y: 0}, theta: Direction.UP, - lineSize: 100000, //360, + lineSize: 100000, lineDist: 650, lineDistMax: 650, decay: TensorMath.new.mult(-1).sum(1).finish, - multiplier: 2200, + multiplier: 2200 }) this.$rulesAttack = new LineIntention('avoid_defence_fault', { - target: {x: 850 , y: 0}, + target: {x: 850, y: 0}, theta: Direction.DOWN, - lineSize: 100000, //360, + lineSize: 100000, lineDist: 650, lineDistMax: 650, decay: TensorMath.new.mult(-1).sum(1).finish, - multiplier: 2200, + multiplier: 2200 }) - + this.addIntetion(this.$rules) this.addIntetion(this.$rulesAttack) - // ============================================== Attack with Acceleration - // this.$attackAccelerated = new Intention('attackAccelerated') - // this.addIntetion(this.$attackAccelerated) - this.$attackAccelerated = this.addIntetion(new PointIntention('goBall', { target: () => { - - // let prop = Vector.size(Vector.sub(this.ball, this.position)) - // if (prop < 100) { - // return {x: 800, y: 0} - // } - // console.log('dist', prop.toFixed(0)) - return {x: this.ball.x, y: this.ball.y} + return {x: this.ball.x, y: this.ball.y} }, radius: OffsetBallDistance + 150, radiusMax: OffsetBallDistance + 150, decay: TensorMath.new.constant(1).finish, - multiplier: this.currentAttackMultiplier.bind(this), + multiplier: this.currentAttackMultiplier.bind(this) })) this.$goGoal = this.addIntetion(new PointIntention('goGoal', { target: {x: 900, y: 0}, - // () => { - // // let prop = Vector.size(Vector.sub(this.ball, this.position)) - // // if (prop < 100) { - // return {x: 800, y: 0} - // // } - // // console.log('dist', prop.toFixed(0)) - // // return {x: this.ball.x, y: this.ball.y} - // }, radius: 150, radiusMax: false, decay: TensorMath.new.finish, - multiplier: 600, + multiplier: 600 })) - - // this.$goGoal = this.addIntetion(new LineIntention('goGoal', { - // target: {x: 900, y: 0}, - // theta: Direction.LEFT, - - // lineSize: 100000, //360, - // lineDist: 650, - // lineDistMax: 650, - // decay: TensorMath.new.mult(-1).sum(1).finish, - // multiplier: 800, - // // () => { - // // // let prop = Vector.size(Vector.sub(this.ball, this.position)) - // // // if (prop < 100) { - // // return {x: 800, y: 0} - // // // } - // // // console.log('dist', prop.toFixed(0)) - // // // return {x: this.ball.x, y: this.ball.y} - // // }, - // // radius: 150, - // // radiusMax: false, - // // decay: TensorMath.new.finish, - // // multiplier: 600, - // })) - } - currentAttackMultiplier(dist) { - // this.$prepareAttack.weight = 0 - - let speed = Math.max(260, Vector.size(this.ballSpeed)*2.0 + 260) - // console.log('speed', speed.toFixed(0)) - return speed + currentAttackMultiplier () { + return Math.max(260, Vector.size(this.ballSpeed) * 2.0 + 260) } - - loop(){ + loop () { let toBall = Vector.sub({x: this.ball.x + 50, y: this.ball.y}, this.position) let toBallDist = Vector.size(toBall) let toBallAngle = Vector.toDegrees(Vector.angle(toBall)) let withinAttackArea = (toBall.x > 0) && Math.abs(toBallAngle) < (35) // 35 - + if (!withinAttackArea) { this.$prepareAttack.weight = 1 this.$attackAccelerated.weight = 0 this.$goGoal.weight = 0 - // console.log('outside', (toBallAngle).toFixed(0)) } else { this.$prepareAttack.weight = 0.5 this.$attackAccelerated.weight = 1 if (toBallDist > 300 || (toBallDist < 120 && this.ballSpeed.x > 300)) { - console.log('inside GO GOAL!', toBallDist.toFixed(0) + '\t'+this.ballSpeed.x.toFixed(0)) + console.log('inside GO GOAL!', toBallDist.toFixed(0) + '\t' + this.ballSpeed.x.toFixed(0)) this.$goGoal.weight = 1 } else { - console.log('inside ', toBallDist.toFixed(0) + '\t'+this.ballSpeed.x.toFixed(0)) + console.log('inside ', toBallDist.toFixed(0) + '\t' + this.ballSpeed.x.toFixed(0)) this.$goGoal.weight = 0 } -// >>>>>>> Stashed changes } - - // this.$prepareAttack.weight = 0 - - // let speed = Math.max(160, Vector.size(this.ballSpeed) + 70) * 2 - // console.log('speed', speed.toFixed(0)) - // return speed - -// <<<<<<< Updated upstream -// this.$avoidWalls.weight = 1 -// console.log(this.getIntentionsInfo()) -// ======= - this.$avoidWalls.weight = 0.3 -// >>>>>>> Stashed changes - // this.$prepareAttack.weight = 1 - // this.$attackAccelerated.weight = 1 - // console.log(this.intentionGroup.output) } -} \ No newline at end of file +} diff --git a/players/BasePlayer.js b/players/BasePlayer.js index 2f921bc..d6fda07 100644 --- a/players/BasePlayer.js +++ b/players/BasePlayer.js @@ -1,8 +1,5 @@ const Vector = require('../lib/Vector') -let fail = 0 -const MAX_ANGULAR = Vector.toRadians(999) - module.exports = class BasePlayer { // TODO Renomear/Reestruturar necessidade de passar id constructor (id, match, options) { @@ -10,41 +7,27 @@ module.exports = class BasePlayer { this.match = match this.options = options this.state = {id: id, class: this.name} - this.ball = {x:0,y:0} + this.ball = {x: 0, y: 0} this.linear = 0 this.angular = 0 - - this.position = {x : 0, y : 0} + this.position = {x: 0, y: 0} this.orientation = 0 - - // if (options.predict) { - // console.log('Enabled prediction for', id) - // setInterval(() => { - // // Skip if no frame has arrived yet - // if (!this.position.x) - // return; - - // this.simulate() - // this.update() - // }, 5) - // } } - get visionId() { + get visionId () { return this.options.visionId } - get radioId() { + get radioId () { return this.options.radioId } - setRobot(robot) { + setRobot (robot) { this.options = robot } - // Update robot state (linear and angular) targets - async send(_state, _linear, _angular) { - if (_state == 1) { + async send (_state, _linear, _angular) { + if (_state === 1) { this.linear = _linear this.angular = _angular } else { @@ -53,41 +36,22 @@ module.exports = class BasePlayer { } } - // isActive() { - // if (!this.frame) { - // return false - // } - // // frame_number: 308954, - // // t_capture: 33517.520055, - // // t_sent: 1513650099.136511, - // // camera_id: 1, - // let delta = Date.now() / 1000 - this.frame.t_sent - // console.log(this.id, 'delta:', this.detection) - - // return Math.abs(delta) < 4 - // } - - simulate(dt) { + simulate (dt) { // Compute dt if not assigned if (!dt) { let now = Date.now() dt = (now - this.lastTime) / 1000 this.lastTime = now } - if (dt > 0.05) { console.error('Dt weird:', dt) return } - let deltaPos = Vector.mult(Vector.fromTheta(this.orientation), dt * -this.linear) let deltaTheta = this.angular * dt if (deltaTheta) { - this.orientation = this.orientation - deltaTheta * Math.PI/180 + this.orientation = this.orientation - deltaTheta * Math.PI / 180 } - - if (deltaPos) - this.position = Vector.sum(this.position, deltaPos) - // console.log('delta: ', Math.round(Vector.toDegrees(deltaTheta))) + if (deltaPos) this.position = Vector.sum(this.position, deltaPos) } -} \ No newline at end of file +} diff --git a/players/Defender.js b/players/Defender.js index f69e111..4d373e2 100644 --- a/players/Defender.js +++ b/players/Defender.js @@ -3,26 +3,18 @@ const TensorMath = require('../lib/TensorMath') const Intention = require('../Intention') const LineIntention = require('../Intention/LineIntention') const PointIntention = require('../Intention/PointIntention') -const LookAtIntention = require('../Intention/LookAtIntention') const Vector = require('../lib/Vector') -// const FORWARD_SPEED = 500 // ~4.3s -const FORWARD_SPEED = 500 // ~4.3s - -const ANGULAR_MULTIPLIER = 10 const Direction = { UP: Math.PI / 2, - DOWN: - Math.PI / 2, + DOWN: -(Math.PI / 2), RIGHT: 0, - LEFT: Math.PI, + LEFT: Math.PI } - -const AvoidWall_Decay = TensorMath.new.finish -const AvoidWall_Speed = 980 -const AvoidWall_Corridor_max = 100 -const AvoidWall_Corridor = 100 -const OffsetBallDistance = 130 - +const AvoidWallDecay = TensorMath.new.finish +const AvoidWallSpeed = 980 +const AvoidWallCorridorMax = 100 +const AvoidWallCorridor = 100 const Field = { width: 1700, TopLeft: {x: -775, y: 675}, @@ -32,39 +24,33 @@ const Field = { } module.exports = class Defender extends IntentionPlayer { - setup(){ - let ball = () => { - return {x: this.ball.x, - y: this.ball.y} - } - // ============================================== Follow Ball in Y while Being in an X + setup () { + // Follow Ball in Y while Being in an X this.$followYIntetion = new Intention('goalkeeper_following') this.addIntetion(this.$followYIntetion) - + this.$followYIntetion.addIntetion(new LineIntention('follow_Y', { - target: () => { return {x:this.ball.x-100, y:this.ball.y}}, + target: () => { return {x: this.ball.x - 100, y: this.ball.y} }, theta: Direction.RIGHT, lineSize: 1700, lineDist: 80, decay: TensorMath.new.pow(2).mult(-1).finish, - multiplier: 600, + multiplier: 600 })) this.$followYIntetion.addIntetion(new LineIntention('follow_X', { - target: {x: -250 , y: 0}, + target: {x: -250, y: 0}, theta: Direction.UP, lineSize: 1700, lineDist: 200, decay: TensorMath.new.pow(2).mult(-1).finish, - multiplier: 600, + multiplier: 600 })) - this.$kickBall = new Intention('pushBall') this.addIntetion(this.$kickBall) - this.$kickBall.addIntetion(new PointIntention('pushBall', { - target: () => { return {x:this.ball.x , y:this.ball.y}}, + target: () => { return {x: this.ball.x, y: this.ball.y} }, radius: 200, radiusMax: 200, decay: TensorMath.new.constant(1).finish, @@ -73,46 +59,32 @@ module.exports = class Defender extends IntentionPlayer { this.$avoidWalls = new Intention('avoid_walls') this.addIntetion(this.$avoidWalls) - - this.$avoidWalls.addIntetion(new LineIntention('topWall', { - // target: ball, target: Field.TopRight, theta: Direction.RIGHT, - lineSize: Field.width, // Largura do segmento de reta - // lineSizeSingleSide: true, - - lineDist: AvoidWall_Corridor, // Tamanho da repelência - lineDistMax: AvoidWall_Corridor_max, // Tamanho da repelência - // lineDistSingleSide: true, - - decay: AvoidWall_Decay, - multiplier: AvoidWall_Speed, + lineSize: Field.width, + lineDist: AvoidWallCorridor, + lineDistMax: AvoidWallCorridorMax, + decay: AvoidWallDecay, + multiplier: AvoidWallSpeed })) this.$avoidWalls.addIntetion(new LineIntention('bottomWall', { - // target: ball, target: Field.BottomLeft, theta: Direction.LEFT, - lineSize: Field.width, // Largura do segmento de reta - lineDist: AvoidWall_Corridor, // Tamanho da repelência - lineDistMax: AvoidWall_Corridor_max, // Tamanho da repelência - decay: AvoidWall_Decay, - multiplier: AvoidWall_Speed, + lineSize: Field.width, + lineDist: AvoidWallCorridor, + lineDistMax: AvoidWallCorridorMax, + decay: AvoidWallDecay, + multiplier: AvoidWallSpeed })) - - - } - loop(){ + loop () { let toBall = Vector.sub({x: this.ball.x, y: this.ball.y}, this.position) - let toBallDist = Vector.size(toBall) let toBallAngle = Vector.toDegrees(Vector.angle(toBall)) - if (Math.abs(toBallAngle) < 10) { - console.log("Inside") + console.log('Inside') } - } -} \ No newline at end of file +} diff --git a/players/GoalKeeper.js b/players/GoalKeeper.js index 69d4957..c605151 100644 --- a/players/GoalKeeper.js +++ b/players/GoalKeeper.js @@ -3,24 +3,14 @@ const TensorMath = require('../lib/TensorMath') const Intention = require('../Intention') const LineIntention = require('../Intention/LineIntention') const PointIntention = require('../Intention/PointIntention') -const LookAtIntention = require('../Intention/LookAtIntention') - -// const FORWARD_SPEED = 500 // ~4.3s -const FORWARD_SPEED = 500 // ~4.3s - -const ANGULAR_MULTIPLIER = 10 const Direction = { UP: Math.PI / 2, - DOWN: - Math.PI / 2, + DOWN: -(Math.PI / 2), RIGHT: 0, - LEFT: Math.PI, + LEFT: Math.PI } -const AvoidWall_Decay = TensorMath.new.finish -const AvoidWall_Speed = 980 -const AvoidWall_Corridor_max = 420 -const AvoidWall_Corridor = 420 const OffsetBallDistance = 130 const Field = { @@ -32,13 +22,11 @@ const Field = { } module.exports = class GoalKeeper extends IntentionPlayer { - setup(){ + setup () { let ball = () => { - return {x: this.ball.x, - y: this.ball.y} + return {x: this.ball.x, y: this.ball.y} } - - // ============================================== Follow Ball in y + // Follow Ball in y this.$followXIntetion = new Intention('goalkeeper_following') this.$followXIntetion.addIntetion(new LineIntention('follow_y', { target: ball, @@ -46,7 +34,7 @@ module.exports = class GoalKeeper extends IntentionPlayer { lineSize: 1700, lineDist: 80, decay: TensorMath.new.mult(-1).finish, - multiplier: 900, + multiplier: 900 })) this.$prepareAttack = new Intention('prepareAttack') @@ -57,58 +45,21 @@ module.exports = class GoalKeeper extends IntentionPlayer { radius: 150, radiusMax: false, decay: TensorMath.new.constant(1).finish, - multiplier: 900, + multiplier: 900 }) this.$prepareAttack.addIntetion(this.$keepCenterGoal) - this.$followXIntetion.addIntetion(new LineIntention('follow_goalline', { - target: {x: this.CENTER_OWN_GOAL + 180 , y: 0}, + target: {x: this.CENTER_OWN_GOAL + 180, y: 0}, theta: Direction.UP, lineSize: 1700, lineDist: 200, - //lineDistMax: 200, - // lineDist: 80, - // lineDistMax: 200, decay: TensorMath.new.mult(-1).finish, - multiplier: 900, + multiplier: 900 })) this.addIntetion(this.$followXIntetion) - // ============================================== Avoid Walls - - // this.$avoidWalls = new Intention('avoid_walls') - // this.$avoidWalls.addIntetion(new LineIntention('topWall', { - // // target: ball, - // target: Field.TopRight, - // theta: Direction.RIGHT, - // lineSize: Field.width, // Largura do segmento de reta - // // lineSizeSingleSide: true, - // lineDist: AvoidWall_Corridor, // Tamanho da repelência - // lineDistMax: AvoidWall_Corridor_max, // Tamanho da repelência - // // lineDistSingleSide: true, - - // decay: AvoidWall_Decay, - // multiplier: AvoidWall_Speed, - // })) - - // this.$avoidWalls.addIntetion(new LineIntention('bottomWall', { - // // target: ball, - // target: Field.BottomLeft, - // theta: Direction.LEFT, - // lineSize: Field.width, // Largura do segmento de reta - // // lineSizeSingleSide: true, - - // lineDist: AvoidWall_Corridor, // Tamanho da repelência - // lineDistMax: AvoidWall_Corridor_max, // Tamanho da repelência - // // lineDistSingleSide: true, - - // decay: AvoidWall_Decay, - // multiplier: AvoidWall_Speed, - // })) - // this.addIntetion(this.$avoidWalls) - - // ============================================== comportamento de libero + // comportamento de libero this.$attackAccelerated = new Intention('attackAccelerated') this.addIntetion(this.$attackAccelerated) @@ -117,13 +68,12 @@ module.exports = class GoalKeeper extends IntentionPlayer { radius: OffsetBallDistance * 2, radiusMax: OffsetBallDistance * 2, decay: TensorMath.new.constant(1).finish, - multiplier: 1200, + multiplier: 1200 })) - } - loop(){ - if (this.ball.x > Field.width/3) { + loop () { + if (this.ball.x > Field.width / 3) { this.$followXIntetion.weight = 0 this.$keepCenterGoal.weight = 1 } else { @@ -131,4 +81,4 @@ module.exports = class GoalKeeper extends IntentionPlayer { this.$keepCenterGoal.weight = 0 } } -} \ No newline at end of file +} diff --git a/players/IntentionPlayer.js b/players/IntentionPlayer.js index 8d83051..8b13707 100644 --- a/players/IntentionPlayer.js +++ b/players/IntentionPlayer.js @@ -1,22 +1,11 @@ -const _ = require('lodash') - -// Math and vector libs const Vector = require('../lib/Vector') const TensorMath = require('../lib/TensorMath') - -// Intentions libs const Intention = require('../Intention') -const LineIntention = require('../Intention/LineIntention') - -// Base player lib const BasePlayer = require('./BasePlayer') module.exports = class IntentionPlayer extends BasePlayer { constructor (id, match, options) { super(id, match, options) - // Constants - - // Position of Field Edges this.Field = { width: 1700, TopLeft: {x: -775, y: 675}, @@ -24,55 +13,38 @@ module.exports = class IntentionPlayer extends BasePlayer { BottomLeft: {x: -775, y: -675}, BottomRight: {x: 775, y: -675} } - - // Util function to sleep - this.sleep = ms => new Promise((res, rej) => setTimeout(res, ms)) - // The Offset between the real ball position and the position that robot will follow this.AtkOffsetBallDistance = 150 - // Centers of your own goal and enemy goal + const SPEED_IMPORTANCE_MIN = 10 + const SPEED_IMPORTANCE_MAX = 35 this.CENTER_OWN_GOAL = -835 this.CENTER_ENEMY_GOAL = 835 - - // Self-explanatory - this.MAX_ROBOT_SPEED=500 - - const SPEED_IMPORTANCE_MIN=10 - const SPEED_IMPORTANCE_MAX=15 - - - this.speedImportance = TensorMath.new.map( - SPEED_IMPORTANCE_MIN, SPEED_IMPORTANCE_MAX, 0, 1).min(1).max(0).finish - // ======================= + this.MAX_ROBOT_SPEED = 500 + this.speedImportance = TensorMath.new.map(SPEED_IMPORTANCE_MIN, SPEED_IMPORTANCE_MAX, 0, 1).min(1).max(0).finish this.intentionGroup = new Intention('RootIntentionGroup') - this.lastBall = null this.ballSpeed = {x: 0, y: 0} this._ballSpeedsRaw = [] this.setup() - // this.orientation = 0 } - addIntetion(intention) { + addIntetion (intention) { this.intentionGroup.addIntetion(intention) return intention } - getIntentionsInfo() { + getIntentionsInfo () { return this.intentionGroup.intentions.map(x => x.getIntentionInfo()) } - setup() {} - loop() {} - - computeRobotModelForIntention({vx, vy, vtheta}) { + computeRobotModelForIntention ({vx, vy, vtheta}) { // Create Vector From Received Speed let targetSpeedVector = {x: vx, y: vy} // Escalar let targetSpeed = Vector.size(targetSpeedVector) - //console.log(targetSpeedVector, targetSpeed) + // Limit to robot limit if (targetSpeed > this.MAX_ROBOT_SPEED) { targetSpeed = this.MAX_ROBOT_SPEED @@ -85,49 +57,38 @@ module.exports = class IntentionPlayer extends BasePlayer { let linear = robotWorldSpeed.x // To work with the two robot fronts - if(robotWorldSpeed.x < 0.0) { - robotWorldSpeed.y = -robotWorldSpeed.y; - robotWorldSpeed.x = -robotWorldSpeed.x; + if (robotWorldSpeed.x < 0.0) { + robotWorldSpeed.y = -robotWorldSpeed.y + robotWorldSpeed.x = -robotWorldSpeed.x } // Use speed vector as robot angle let robotAngleToSpeed = -Vector.angle(robotWorldSpeed) - let speedWeight = this.speedImportance(targetSpeed) let vthetaWeight = 1 - speedWeight - // console.log(vthetaWeight) - let angular = (robotAngleToSpeed * 120 * speedWeight) + (vtheta * vthetaWeight) - //console.log(linear, angular) + let angular = (robotAngleToSpeed * 160 * speedWeight) + (vtheta * vthetaWeight) return {linear, angular} } - async update() { - if(this.match.state._state.status == 'stopped'){ + async update () { + if (this.match.state._state.status === 'stopped') { this.send(0, 0, 0) return [this.radioId, 0, 0, 0] } - if(this.frame){ + if (this.frame) { let frame = this.frame - // Update ball position - // console.log(frame) - if(frame.balls[0]){ + if (frame.balls[0]) { this.lastBall = this.ball - - let dt = this.frame.t_capture - this.lastBallTimestamp + const dt = this.frame.t_capture - this.lastBallTimestamp this.lastBallTimestamp = this.frame.t_capture - this.ball = frame.balls[0] - if (dt && dt < 0.04 && this.lastBall) { - this._ballSpeedsRaw.unshift({ x: (this.ball.x - this.lastBall.x) / dt, - y: (this.ball.y - this.lastBall.y) / dt, + y: (this.ball.y - this.lastBall.y) / dt }) - this._ballSpeedsRaw = this._ballSpeedsRaw.slice(0, 10) - let avgSpeed = this._ballSpeedsRaw.reduce((last, speed) => { return {x: last.x + speed.x, y: last.y + speed.y} }, {x: 0, y: 0}) @@ -136,30 +97,21 @@ module.exports = class IntentionPlayer extends BasePlayer { avgSpeed.y = avgSpeed.y / this._ballSpeedsRaw.length this.ballSpeed = avgSpeed - - // console.log(dt + '\t' + avgSpeed.x.toFixed(0) + '\t' + avgSpeed.y.toFixed(0)) } - // Compute ball average speed - // let sum = this.lastBalls.reduce((prev, ball) => {prev}) } - } else{ - console.error("Frame not present in IntentionPlayer") + } else { + console.error('Frame not present in IntentionPlayer') } await this.loop() - - // Prepare input for intentions let input = { x: this.position.x, y: this.position.y, - theta: this.orientation, + theta: this.orientation } - // Get intention output let output = this.intentionGroup.compute(input) - // Convert to robot model let {linear, angular} = this.computeRobotModelForIntention(output) - // Apply to robot this.send(1, linear, angular) return [this.radioId, 1, linear, angular] diff --git a/players/NewAttacker.js b/players/NewAttacker.js index 4bdef77..9d0e514 100644 --- a/players/NewAttacker.js +++ b/players/NewAttacker.js @@ -1,8 +1,5 @@ -// Math and vetor libs const Vector = require('../lib/Vector') const TensorMath = require('../lib/TensorMath') - -// Intentions lib const Intention = require('../Intention') const IntentionPlayer = require('./IntentionPlayer') const LineIntention = require('../Intention/LineIntention') @@ -10,50 +7,39 @@ const PointIntention = require('../Intention/PointIntention') const LookAtIntention = require('../Intention/LookAtIntention') module.exports = class NewAttacker extends IntentionPlayer { - setup(){ - - let ball = () => {return this.ball} + setup () { + const ball = () => this.ball this.orientation = Math.PI / 2 this.position = {x: 0, y: 40} - - - - - // ============================================== Prepare Attack + // Prepare Attack this.$prepareAttack = new Intention('prepareAttack') this.addIntetion(this.$prepareAttack) - this.$prepareAttack.addIntetion(new LineIntention('angularAvoidOwnGoal1', + this.$prepareAttack.addIntetion(new LineIntention('angularAvoidOwnGoal1', { target: ball, - theta: Vector.direction("right"), + theta: Vector.direction('right'), lineSize: 400, lineSizeSingleSide: true, lineDist: 120, lineDistMax: 120, decay: TensorMath.new.sub(1).mult(-1).finish, - multiplier: 450, + multiplier: 450 } )) this.$prepareAttack.addIntetion(new PointIntention('followBall', { target: () => { - return {x: this.ball.x -100, y: this.ball.y} + return {x: this.ball.x - 100, y: this.ball.y} }, radius: 400, radiusMax: 2000, decay: TensorMath.new.finish, multiplier: 500 - })) - - - - - - - // ============================================== Make Goal - this.$makeGoal = new Intention("makeGoal") + })) + // Make Goal + this.$makeGoal = new Intention('makeGoal') this.addIntetion(this.$makeGoal) this.$makeGoal = this.addIntetion(new PointIntention('goGoal', { @@ -61,7 +47,7 @@ module.exports = class NewAttacker extends IntentionPlayer { radius: 800, radiusMax: 2000, decay: TensorMath.new.sub(1).mult(-2).finish, - multiplier: 500, + multiplier: 500 })) this.$makeGoal.addIntetion(new LineIntention('followYBall', { @@ -76,19 +62,13 @@ module.exports = class NewAttacker extends IntentionPlayer { decay: TensorMath.new.finish })) - - - - -// ====================== - - this.$pushBall = new Intention("pushBall") + this.$pushBall = new Intention('pushBall') this.addIntetion(this.$pushBall) this.$pushBall = this.addIntetion(new LookAtIntention('lookball', { target: ball, decay: TensorMath.new.finish, - multiplier: 10, + multiplier: 10 })) this.$pushBall.addIntetion(new PointIntention('followBall', { @@ -100,84 +80,37 @@ module.exports = class NewAttacker extends IntentionPlayer { decay: TensorMath.new.finish })) - // this.ballSpeedInit = this.ballSpeed - - this.$followBallOnBoarder = new Intention("followBallOnBoarder") - - // this.$followBallOnBoarder = this.addIntetion(new PointIntention('followBallOnBoard', { - // target: ball, - // radius: 700, - // radiusMax: false, - // decay: TensorMath.new.sub(1).mult(-2).finish, - // multiplier: () => { - // return Vector.size(this.ballSpeed) * 2 + 300 - // }, - // })) - + this.$followBallOnBoarder = new Intention('followBallOnBoarder') this.$rules = new Intention('rules') - - // this.$rules = this.addIntetion(new PointIntention('avoidGoalArea', { - // target: {x: -300, y: 0}, - // theta: Vector.direction('up'), - // radius: 250, - // decay: TensorMath.new.finish, - // multiplier: 4000 - // })) } - loop(){ - + loop () { let toBall = Vector.sub(this.ball, this.position) - let toBallDist = Vector.size(toBall) - let toBallAngle = Vector.toDegrees(Vector.angle(toBall)) let toGoalAngle = Vector.toDegrees(Vector.angle({x: this.CENTER_ENEMY_GOAL, y: this.position.y})) - - let diffBetweenAngles = toGoalAngle+toBallAngle - + let diffBetweenAngles = toGoalAngle + toBallAngle let absoluteDiffAngles = Math.abs(diffBetweenAngles) - // if(absoluteDiffAngles < 20) { - // let goalWeight = (30 - absoluteDiffAngles)/30 - // if (goalWeight < 0.1) { - // // this.$makeGoal.weight = 1 - // }else { - // // this.$makeGoal.weight = goalWeight - // } - // } else { - // // this.$makeGoal.weight = 0 - // } - if(absoluteDiffAngles < 30) { + + if (absoluteDiffAngles < 30) { this.$makeGoal.weight = 1 this.$prepareAttack.weight = 0 this.$pushBall.weight = 0 - console.log("Inside Make") - - }else if(absoluteDiffAngles >= 30 && absoluteDiffAngles < 60){ + console.log('Inside Make') + } else if (absoluteDiffAngles >= 30 && absoluteDiffAngles < 60) { this.$makeGoal.weight = 0 this.$prepareAttack.weight = 0 this.$pushBall.weight = 1 - console.log("Inside Push") - } - else{ + console.log('Inside Push') + } else { this.$makeGoal.weight = 0 this.$prepareAttack.weight = 1 this.$pushBall.weight = 0 - console.log("Inside Prepare") + console.log('Inside Prepare') } - - - // if(this.ball.x < -400) { - // this.$rules.weight = 1 - // this.$prepareAttack.weight = 0 - // } else { - // this.$rules.weight = 0 - // this.$prepareAttack.weight = 1 - // } - - if(Math.abs(this.ball.y) > 640) { + if (Math.abs(this.ball.y) > 640) { this.$pushBall.weight = 1 } else { this.$pushBall.weight = 0 } } -} \ No newline at end of file +} diff --git a/players/NewGoalKeeper.js b/players/NewGoalKeeper.js index 41d81c3..1576db1 100644 --- a/players/NewGoalKeeper.js +++ b/players/NewGoalKeeper.js @@ -1,8 +1,6 @@ // Math and vetor libs const Vector = require('../lib/Vector') const TensorMath = require('../lib/TensorMath') - -// Intentions lib const Intention = require('../Intention') const IntentionPlayer = require('./IntentionPlayer') const LineIntention = require('../Intention/LineIntention') @@ -10,119 +8,96 @@ const PointIntention = require('../Intention/PointIntention') const LookAtIntention = require('../Intention/LookAtIntention') const MIN_BASE_LINEAR_SPEED = 300 -const AvoidWall_Decay = TensorMath.new.constant(1).finish -const AvoidWall_Speed = 980 -const AvoidWall_Corridor_max = 430 -const AvoidWall_Corridor = 430 +const AvoidWallDecay = TensorMath.new.constant(1).finish +const AvoidWallSpeed = 980 +const AvoidWallCorridorMax = 430 +const AvoidWallCorridor = 430 const OffsetBallDistance = 130 module.exports = class NewGoalKeeper extends IntentionPlayer { - setup(){ - - let ball = () => {return this.ball} + setup () { + const ball = () => { return this.ball } this.orientation = Math.PI / 2 this.position = {x: 0, y: 40} - - // ============================================== Defend the goal + // Defend the goal this.$defend = new Intention('defend') this.addIntetion(this.$defend) - // --------------------------- Follow the y of the ball fixed on a x - this.$defend.addIntetion(new LineIntention("followBallToDefend", { + // Follow the y of the ball fixed on a x + this.$defend.addIntetion(new LineIntention('followBallToDefend', { target: () => { - return {x: this.CENTER_OWN_GOAL + 200, y: this.ball.y } - }, - theta: Vector.direction("right"), + return {x: this.CENTER_OWN_GOAL + 200, y: this.ball.y} + }, + theta: Vector.direction('right'), multiplier: MIN_BASE_LINEAR_SPEED, decay: TensorMath.new.mult(-1).finish, lineSize: 1700, lineDist: 80 })) - // ---------------------------- Look to the ball - this.$defend.addIntetion(new LookAtIntention('lookAtBall', - { - target: () => {return {x: this.ball.x - 50, y: this.ball.y}}, + // Look to the ball + this.$defend.addIntetion(new LookAtIntention('lookAtBall', { + target: () => { return {x: this.ball.x - 50, y: this.ball.y} }, decay: TensorMath.new.finish, multiplier: 20 })) - // ---------------------------- Maintain in the line X of the goal + // Maintain in the line X of the goal this.$defend.addIntetion(new LineIntention('follow_goalline', { - target: {x: this.CENTER_OWN_GOAL + 200 , y: 0}, - theta: Vector.direction("up"), + target: {x: this.CENTER_OWN_GOAL + 200, y: 0}, + theta: Vector.direction('up'), lineSize: 1700, lineDist: 200, decay: TensorMath.new.mult(-1).finish, - multiplier: MIN_BASE_LINEAR_SPEED + 200, + multiplier: MIN_BASE_LINEAR_SPEED + 200 })) - // ============================================ end Defend the goal - - // ============================================ Repel the Ball + // end Defend the goal + + // Repel the Ball this.$prepareAttack = new Intention('attackAccelerated') this.addIntetion(this.$prepareAttack) - this.$prepareAttack.addIntetion(new PointIntention('goBall', { target: ball, radius: OffsetBallDistance * 4, radiusMax: OffsetBallDistance * 4, decay: TensorMath.new.constant(1).finish, - multiplier: MIN_BASE_LINEAR_SPEED + 200, + multiplier: MIN_BASE_LINEAR_SPEED + 200 })) - // ============================================ end Repel the Ball + // end Repel the Ball - // ============================================ Dont go to the sides + // Dont go to the sides this.$avoidWalls = new Intention() this.$avoidWalls.addIntetion(new LineIntention('topWall', { - // target: ball, target: this.Field.TopRight, - theta: Vector.direction("left"), - lineSize: this.Field.width, // Largura do segmento de reta + theta: Vector.direction('left'), + lineSize: this.Field.width, lineSizeSingleSide: true, - lineDist: AvoidWall_Corridor, // Tamanho da repelência - lineDistMax: AvoidWall_Corridor_max, // Tamanho da repelência - // lineDistSingleSide: true, - - decay: AvoidWall_Decay, - multiplier: AvoidWall_Speed, + lineDist: AvoidWallCorridor, + lineDistMax: AvoidWallCorridorMax, + decay: AvoidWallDecay, + multiplier: AvoidWallSpeed })) - this.$avoidWalls.addIntetion(new LineIntention('bottomWall', { - // target: ball, target: this.Field.BottomLeft, - theta: Vector.direction("right"), - lineSize: this.Field.width, // Largura do segmento de reta + theta: Vector.direction('right'), + lineSize: this.Field.width, lineSizeSingleSide: true, - - lineDist: AvoidWall_Corridor, // Tamanho da repelência - lineDistMax: AvoidWall_Corridor_max, // Tamanho da repelência - // lineDistSingleSide: true, - - decay: AvoidWall_Decay, - multiplier: AvoidWall_Speed, + lineDist: AvoidWallCorridor, + lineDistMax: AvoidWallCorridorMax, + decay: AvoidWallDecay, + multiplier: AvoidWallSpeed })) this.addIntetion(this.$avoidWalls) - // ============================================ end Dont go to the sides + // end Dont go to the sides this.ballSpeedInit = this.ballSpeed } - loop(){ - let toBall = Vector.sub(this.ball, this.position) - let toBallDist = Vector.size(toBall) - - let bola = this.ballSpeed - let realBallSpeed = Vector.size(Vector.sub(bola,this.ballSpeedInit)).toFixed(1) - - let toBallAngle = Vector.toDegrees(Vector.angle(toBall)) - let toGoalAngle = Vector.toDegrees(Vector.angle({x: this.CENTER_ENEMY_GOAL, y: this.position.y})) - - let diffBetweenAngles = toGoalAngle + toBallAngle - + loop () { if (this.ball.x < -380) { this.$defend.weight = 0 this.$prepareAttack.weight = 1 this.$avoidWalls.weight = 0 - }else { + } else { this.$defend.weight = 1 this.$prepareAttack.weight = 0 this.$avoidWalls.weight = 1 } } -} \ No newline at end of file +} diff --git a/players/TestPlayer.js b/players/TestPlayer.js index d567bbc..48004eb 100644 --- a/players/TestPlayer.js +++ b/players/TestPlayer.js @@ -1,104 +1,65 @@ const IntentionPlayer = require('./IntentionPlayer') const TensorMath = require('../lib/TensorMath') const Intention = require('../Intention') -const LineIntention = require('../Intention/LineIntention') const PointIntention = require('../Intention/PointIntention') const LookAtIntention = require('../Intention/LookAtIntention') const FORWARD_SPEED = 15 // ~4.3s - const ANGULAR_MULTIPLIER = 200 module.exports = class TestPlayer extends IntentionPlayer { - setup(){ - let ball = () => { - return {x: this.ball.x, - y: this.ball.y - } - } - - // ----------------------------- Go Center Up + setup () { + // Go Center Up this.$goCenterUp = new Intention('goCenterUp') this.$goCenterUp.addIntetion(new PointIntention('center', { - // target: ball, target: {x: -600, y: 0}, radius: 150, radiusMax: false, decay: TensorMath.new.pow(3).finish, - multiplier: FORWARD_SPEED, + multiplier: FORWARD_SPEED })) - this.$goCenterUp.addIntetion(new LookAtIntention('lookUp', { - // target: , theta: Math.PI / 2, decay: TensorMath.new.finish, multiplier: ANGULAR_MULTIPLIER })) - this.addIntetion(this.$goCenterUp) - - - // ----------------------------- Go Goal up + // Go Goal up this.$goGoalUp = new Intention('goGoalUp') this.$goGoalUp.addIntetion(new PointIntention('center', { - // target: ball, target: {x: 600, y: 0}, radius: 150, radiusMax: false, decay: TensorMath.new.pow(3).finish, - multiplier: FORWARD_SPEED, + multiplier: FORWARD_SPEED })) this.$goGoalUp.addIntetion(new LookAtIntention('lookUp', { - // target: , theta: Math.PI / 2, decay: TensorMath.new.finish, - multiplier: ANGULAR_MULTIPLIER, + multiplier: ANGULAR_MULTIPLIER })) this.addIntetion(this.$goGoalUp) - - - // ----------------------------- Avoidance + // Avoidance this.$playerAvoidance = new Intention('playerAvoidance') this.$playerAvoidance.addIntetion(new PointIntention('center', { - // target: ball, target: {x: 0, y: 0}, - radius:150, + radius: 150, radiusMax: 150, decay: TensorMath.new.pow(3).finish, - multiplier: -FORWARD_SPEED, + multiplier: -FORWARD_SPEED })) - this.startTime = Date.now() this.states = [this.$goGoalUp, this.$goCenterUp] - } - loop(){ - + loop () { let current = this.states[0] - this.states.map(state => state.weight = 0) + this.states.map(state => { state.weight = 0 }) current.weight = 1 - if (current.isStabilized()) { - - // let now = Date.now() - // let timeTaken = ((now - this.startTime) / 1000).toFixed(2) - // this.startTime = now - // console.log('completed', current.name, 'in', timeTaken+'s') - current.output = null this.states.unshift(this.states.pop()) } - // console.log(this.frame) - // if (this.$goGoalUp.active && this.$goGoalUp.isStabilized()) { - // this.$goGoalUp.weight = 0 - // this.$goCenterUp.weight = 1 - // } - - // if (this.$goCenterUp.output) { - // console.log(stabilizedIntention(this.$goCenterUp)) - // } - // console.log(this.position) } -} \ No newline at end of file +} diff --git a/players/experimental/Attacker2Base.js b/players/experimental/Attacker2Base.js new file mode 100644 index 0000000..8bff60c --- /dev/null +++ b/players/experimental/Attacker2Base.js @@ -0,0 +1,47 @@ +// const IntentionPlayer = require('../IntentionPlayer') +// const TensorMath = require('../../lib/TensorMath') +// const Intention = require('../../Intention') +// const LineIntention = require('../../Intention/LineIntention') +// const PointIntention = require('../../Intention/PointIntention') +// const LookAtIntention = require('../../Intention/LookAtIntention') +// const OrbitalIntention = require('../../Intention/OrbitalIntention') +// const Vector = require('../../lib/Vector') +// const RulePlays = require('./RulePlays') + +// const BASE_SPEED = 65 + +// module.exports = class Attacker2Base extends RulePlays { +// setup () { +// super.setup() +// let ballAntecipation = () => { +// let ball = {x: this.match.dataManager.ball.x, y: this.match.dataManager.ball.y} +// let ballToCenterGoal = Vector.sub({x: 700, y: 0}, ball) +// let ballToCenterGoalNorm = Vector.norm(ballToCenterGoal) +// let antecipation = { +// x: ballToCenterGoalNorm.x * 110, +// y: ballToCenterGoalNorm.y * 110 +// } +// antecipation = {x: ball.x - antecipation.x, y: ball.y - antecipation.y} +// return antecipation +// } + +// let ball = () => { +// let ball = {x: this.match.dataManager.ball.x, y: this.match.dataManager.ball.y} +// return ball +// } + +// this.addIntetion(new LineIntention('avoidFromOwnGoal', { +// target: {x: -700, y: 0}, +// theta: Vector.direction("down"), +// lineSize: 400, // Largura do segmento de reta +// lineDist: 150, // Tamanho da repelência +// lineDistMax: 150, +// lineDistSingleSide: true, +// decay: TensorMath.new.mult(-1).finish, +// multiplier: 100 +// })) + +// } +// loop(){ +// } +// } diff --git a/players/experimental/AttackerConduct.js b/players/experimental/AttackerConduct.js new file mode 100644 index 0000000..d6ebd56 --- /dev/null +++ b/players/experimental/AttackerConduct.js @@ -0,0 +1,88 @@ +const Vector = require('../../lib/Vector') +const TensorMath = require('../../lib/TensorMath') +const PointIntention = require('../../Intention/PointIntention') +const LookAtIntention = require('../../Intention/LookAtIntention') +const LineIntention = require('../../Intention/LineIntention') + +const RulePlays = require('./RulePlays') + +const BASE_SPEED = 65 + +let robot_saw_the_ball_multiplier = 1.3 + +module.exports = class AttackerConduct extends RulePlays { + setup(){ + super.setup() + let ball = () => { + + return { + x: this.frame.cleanData.ball.x, + y: this.frame.cleanData.ball.y + } + } + + let ballToGoalNormal = () => { + let b = this.frame.cleanData.ball + let c = {x: 680, y: 0} + + let ballToGoal = Vector.sub(b, c) + + // Vector normal + ballToGoal = Vector.norm({x: ballToGoal.x, y: -ballToGoal.y}) + + return Vector.angle(ballToGoal) + } + + this.addIntetion(new PointIntention('KeepOnBall', { + target: ball, + radius: 110, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED + })) + + this.addIntetion(new LineIntention('ConductBall', { + target: ball, + theta: ballToGoalNormal, + lineSize: 75, + lineSizeMax: 75, + lineDist: 100, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * robot_saw_the_ball_multiplier + })) + + // Impedir bater na parede + this.avoidFieldWalls1 = new LineIntention('avoidFieldWalls', { + target: {x:0, y: 610}, + theta: Vector.direction("left"), + lineSize: 1700, + lineDist: 30, + lineDistMax: 30, + decay: TensorMath.new.sum(1).mult(-1).finish, + multiplier: BASE_SPEED * 2 + }) + + this.addIntetion(this.avoidFieldWalls1) + + // Impedir bater na parede + this.avoidFieldWalls2 = new LineIntention('avoidFieldWalls', { + target: {x:0, y: -610}, + theta: Vector.direction("left"), + lineSize: 1700, + lineDist: 30, + lineDistMax: 30, + decay: TensorMath.new.sum(1).mult(-1).finish, + multiplier: BASE_SPEED * 2 + }) + this.addIntetion(this.avoidFieldWalls2) + + this.lookToBall = new LookAtIntention('look_to_ball', { + target: ball, + decay: TensorMath.new.pow(1/2).finish, + multiplier: 640 + }) + this.addIntetion(this.lookToBall) + } + loop(){ + } + +} diff --git a/players/experimental/AttackerHold.js b/players/experimental/AttackerHold.js new file mode 100644 index 0000000..057c96c --- /dev/null +++ b/players/experimental/AttackerHold.js @@ -0,0 +1,60 @@ +const Vector = require('../../lib/Vector') +const TensorMath = require('../../lib/TensorMath') +const OrbitalIntention = require('../../Intention/OrbitalIntention') +const PointIntention = require('../../Intention/PointIntention') +const LookAtIntention = require('../../Intention/LookAtIntention') +const LineIntention = require('../../Intention/LineIntention') + +const RulePlays = require('./RulePlays') +const BASE_SPEED = 50 + +module.exports = class AttackerHold extends RulePlays { + setup () { + super.setup() + let ballProjection = () => { + return { + x: -200, + y: this.frame.cleanData.ball.y * 2 + } + } + + this.addIntetion(new PointIntention('KeepOnBall', { + target: ballProjection, + radius: 110, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED + })) + + // Impedir bater na parede + this.avoidFieldWalls1 = new LineIntention('avoidFieldWalls', { + target: {x:0, y: 610}, + theta: Vector.direction("left"), + lineSize: 1700, + lineDist: 30, + lineDistMax: 30, + decay: TensorMath.new.sum(1).mult(-1).finish, + multiplier: BASE_SPEED * 2 + }) + + this.addIntetion(this.avoidFieldWalls1) + + // Impedir bater na parede + this.avoidFieldWalls2 = new LineIntention('avoidFieldWalls', { + target: {x:0, y: -610}, + theta: Vector.direction("left"), + lineSize: 1700, + lineDist: 30, + lineDistMax: 30, + decay: TensorMath.new.sum(1).mult(-1).finish, + multiplier: BASE_SPEED * 2 + }) + this.addIntetion(this.avoidFieldWalls2) + + } + loop () { + let ball = { + x: this.frame.cleanData.ball.x, + y: this.frame.cleanData.ball.y + } + } +} diff --git a/players/experimental/AttackerMain.js b/players/experimental/AttackerMain.js new file mode 100644 index 0000000..081ce0d --- /dev/null +++ b/players/experimental/AttackerMain.js @@ -0,0 +1,126 @@ +const Vector = require('../../lib/Vector') +const TensorMath = require('../../lib/TensorMath') +const OrbitalIntention = require('../../Intention/OrbitalIntention') +const PointIntention = require('../../Intention/PointIntention') +const LineIntention = require('../../Intention/LineIntention') + +const RulePlays = require('./RulePlays') + +const BASE_SPEED = 50 + +module.exports = class AttackerMain extends RulePlays { + setup(){ + super.setup() + let ball = () => { + + return { + x: this.frame.cleanData.ball.x, + y: this.frame.cleanData.ball.y + } + } + + let ballShiftedP = () => { + let ball = { + x: this.frame.cleanData.ball.x - 40, + y: this.frame.cleanData.ball.y + 150 + } + return ball + } + + let ballShiftedN = () => { + let ball = { + x: this.frame.cleanData.ball.x - 40, + y: this.frame.cleanData.ball.y - 150 + } + return ball + } + + let ballToGoalNormal = () => { + let b = this.frame.cleanData.ball + let c = {x: 680, y: 0} + + let ballToGoal = Vector.sub(b, c) + + // Vector normal + ballToGoal = Vector.norm({x: ballToGoal.x, y: -ballToGoal.y}) + + return Vector.angle(ballToGoal) + } + + this.orbitalRight = new OrbitalIntention('FollowBall', { + target: ballShiftedN, + clockwise: -1, + radius: 75, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * 0.7 + }) + + this.addIntetion(this.orbitalRight) + + this.orbitalLeft = new OrbitalIntention('FollowBall', { + target: ballShiftedP, + clockwise: 1, + radius: 75, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * 0.7 + }) + + this.addIntetion(this.orbitalLeft) + + /* + Aproxima o robo da bola quando ele esta a 10 cm dela. + O torna mais rapido e mais preciso na interceptação da mesma. + Deve ser mais fraca que o movimento orbial para não cagar. + */ + this.addIntetion(new PointIntention('KeepOnBall', { + target: ball, + radius: 110, + radiusMax: 110, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED + })) + + this.addIntetion(new PointIntention('KeepOnBall', { + target: ball, + radius: 500, + decay: TensorMath.new.sin().finish, + multiplier: BASE_SPEED * 0.7 + })) + + this.avoidFieldWalls3 = new LineIntention('avoidFieldWalls3', { + target: {x:-780, y: 0}, + theta: Vector.direction("up"), + lineSize: 1700, + lineDist: 100, + lineDistMax: 100, + decay: TensorMath.new.sum(1).mult(-1).finish, + multiplier: BASE_SPEED + }) + this.addIntetion(this.avoidFieldWalls3) + + } + loop () { + console.log(this.frame.cleanData.ball.y) + const FIELD_ORBITAL_MARGIN = 200 + + let ball = { + x: this.frame.cleanData.ball.x, + y: this.frame.cleanData.ball.y + } + + if (this.position.y < (-650 + FIELD_ORBITAL_MARGIN)) { + this.orbitalRight.weight = 0 + this.orbitalLeft.weight = 1 + }else if (this.position.y > (650 - FIELD_ORBITAL_MARGIN)) { + this.orbitalRight.weight = 1 + this.orbitalLeft.weight = 0 + + } else if (this.position.y > ball.y) { + this.orbitalRight.weight = 0 + this.orbitalLeft.weight = 1 + } else { + this.orbitalRight.weight = 1 + this.orbitalLeft.weight = 0 + } + } +} diff --git a/players/experimental/AttackerTriangle.js b/players/experimental/AttackerTriangle.js new file mode 100644 index 0000000..9fadf8d --- /dev/null +++ b/players/experimental/AttackerTriangle.js @@ -0,0 +1,74 @@ +const IntentionPlayer = require('../IntentionPlayer') +const TensorMath = require('../../lib/TensorMath') +const Intention = require('../../Intention') +const LineIntention = require('../../Intention/LineIntention') +const PointIntention = require('../../Intention/PointIntention') +const LookAtIntention = require('../../Intention/LookAtIntention') +const OrbitalIntention = require('../../Intention/OrbitalIntention') +const Vector = require('../../lib/Vector') +const RulePlays = require('./RulePlays') + +const BASE_SPEED = 70 + +module.exports = class AttackerTriangle extends RulePlays { + setup () { + super.setup() + + let ball = () => { + return { + x: this.frame.cleanData.ball.x, + y: this.frame.cleanData.ball.y + } + } + + let ballToGoalNormal = () => { + let b = this.frame.cleanData.ball + let c = {x: 680, y: 0} + + let ballToGoal = Vector.sub(b, c) + + // Vector normal + ballToGoal = Vector.norm({x: ballToGoal.x, y: -ballToGoal.y}) + + return Vector.angle(ballToGoal) +} + +const ballToGoal = () => { + let b = this.frame.cleanData.ball + let c = {x: 680, y: 0} + + return Vector.angle(Vector.sub(b, c)) +} + +this.addIntetion(new LineIntention('To the goal', { + target: ball, + theta: ballToGoalNormal, + lineSize: 150, + lineDist: 200, + lineDistMax: 200, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED, + lineDistSingleSide: true +})) + +this.addIntetion(new LineIntention('Keep eye on goal', { + target: ball, + theta: ballToGoal, + lineSize: 2000, + lineDist: 200, + lineDistMax: 200, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * 1.2 +})) + + this.addIntetion(new PointIntention('goBall', { + target: ball, + radius: 150, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED, + })) + +} +loop(){ +} +} diff --git a/players/experimental/BaseMidfielder.js b/players/experimental/BaseMidfielder.js index dc6bbd2..b7b862d 100644 --- a/players/experimental/BaseMidfielder.js +++ b/players/experimental/BaseMidfielder.js @@ -10,19 +10,19 @@ const RulePlays = require('../experimental/RulePlays') module.exports = class BaseMidfielder extends RulePlays { setup () { super.setup() - let attacker = () => { - let pos = this.match.gameManager.coach.attackerRobot.robots.self.position - /* - A projeção não é usada nos casos onde: - - Não existe vetor projeção (ocorre no primeiro frame de execução) - - Velocidade da bola inferior a 1.2 cm/s (praticamente parada) - - Quando a bola ira bater longe do gol (acima de 30 cm em relação ao centro do gol) - */ - return pos - } + // let attacker = () => { + // let pos = this.match.gameManager.coach.attackerRobot.robots.self.position + // /* + // A projeção não é usada nos casos onde: + // - Não existe vetor projeção (ocorre no primeiro frame de execução) + // - Velocidade da bola inferior a 1.2 cm/s (praticamente parada) + // - Quando a bola ira bater longe do gol (acima de 30 cm em relação ao centro do gol) + // */ + // return pos + // } this.addIntetion(new PointIntention('avoidPartner', { - target: attacker, + target: {x:0, y:0}, radius: 400, radiusMax: 400, decay: TensorMath.new.mult(-1).finish, diff --git a/players/experimental/GoalKeeperKeep.js b/players/experimental/GoalKeeperKeep.js new file mode 100644 index 0000000..2c8107d --- /dev/null +++ b/players/experimental/GoalKeeperKeep.js @@ -0,0 +1,39 @@ +const TensorMath = require('../../lib/TensorMath') +const LineIntention = require('../../Intention/LineIntention') +const PointIntention = require('../../Intention/PointIntention') +const Vector = require('../../lib/Vector') +const RulePlays = require('./RulePlays') + +const BASE_SPEED = 40 +const MAX_SPEED = 80 + +const GOAL_LINE = -670 + +module.exports = class GoalkeeperKeep extends RulePlays { + setup(){ + super.setup() + + // Fixar goleiro na linha do gol + this.addIntetion(new LineIntention('KeepGoalLine', { + target: {x: GOAL_LINE, y: 0}, + theta: Vector.direction("up"), + lineSize: 1700, + lineDist: 260, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * 1.6 + })) + + this.addIntetion(new PointIntention('followCrossBall', { + target: {x: GOAL_LINE, y: 0}, + radius: 150, + radiusMax: false, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED + })) + + + } + + loop(){ + } +} diff --git a/players/experimental/GoalKeeperPush2.js b/players/experimental/GoalKeeperPush2.js new file mode 100644 index 0000000..547955f --- /dev/null +++ b/players/experimental/GoalKeeperPush2.js @@ -0,0 +1,54 @@ +const TensorMath = require('../../lib/TensorMath') +const LineIntention = require('../../Intention/LineIntention') +const PointIntention = require('../../Intention/PointIntention') +const LookAtIntention = require('../../Intention/LookAtIntention') +const RulePlays = require('./RulePlays') +const Vector = require('../../lib/Vector') + +const BASE_SPEED = 60 +const GOAL_LINE = -670 + +module.exports = class GoalkeeperPush2 extends RulePlays { + setup(){ + super.setup() + let ball = () => { + let ball = {x: this.frame.cleanData.ball.x, y: this.frame.cleanData.ball.y} + return ball + } + // Fixar goleiro na linha do gol + this.addIntetion(new LineIntention('KeepGoalLine', { + target: {x: GOAL_LINE, y: 0}, + theta: Vector.direction("up"), + lineSize: 1700, + lineDist: 260, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * 1.6 + })) + + //Mantem o goleiro fixado na bola, seguindo eixo Y + this.addIntetion(new LineIntention('KeepOnBall', { + target: ball, + theta: Vector.direction("left"), + lineSize: 1700, + lineDist: 250, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * 1.4 + })) + + /* + Correção na função para o goleiro ter mais velocidade + em casos de bola muito proxima do eixo Y + */ + this.addIntetion(new PointIntention('KeepOnBall', { + target: ball, + radius: 100, + radiusMax: 100, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * 1.4 + })) + } + + loop(){ + + } +} diff --git a/players/experimental/GoalkeeperMain.js b/players/experimental/GoalkeeperMain.js index b55b7fd..c713cdf 100644 --- a/players/experimental/GoalkeeperMain.js +++ b/players/experimental/GoalkeeperMain.js @@ -1,9 +1,5 @@ -const IntentionPlayer = require('../IntentionPlayer') const TensorMath = require('../../lib/TensorMath') -const Intention = require('../../Intention') const LineIntention = require('../../Intention/LineIntention') -const PointIntention = require('../../Intention/PointIntention') -const LookAtIntention = require('../../Intention/LookAtIntention') const Vector = require('../../lib/Vector') const RulePlays = require('./RulePlays') @@ -13,40 +9,41 @@ module.exports = class GoalkeeperMain extends RulePlays { setup(){ super.setup() let ball = () => { - let ball = {x: this.match.dataManager.ball.x, y: this.match.dataManager.ball.y} + let ball = {x: this.frame.cleanData.ball.x, y: this.frame.cleanData.ball.y} return ball } let ballProjection = () => { - let pos = this.match.dataManager.ball.projection - let ballSpeed = this.match.dataManager.ball.speed - let ballPos = {x: this.match.dataManager.ball.x, y: this.match.dataManager.ball.y} + let pos = this.frame.cleanData.ball.projection + let ballSpeed = this.frame.cleanData.ball.speed + let ballPos = {x: this.frame.cleanData.ball.x, y: this.frame.cleanData.ball.y} /* A projeção não é usada nos casos onde: - Não existe vetor projeção (ocorre no primeiro frame de execução) - Velocidade da bola inferior a 1.2 cm/s (praticamente parada) - Quando a bola ira bater longe do gol (acima de 30 cm em relação ao centro do gol) */ - if (!pos || Vector.size(ballSpeed) < 1.2 || Math.abs(pos.y) > 300 ) { - if (Math.abs(ballPos.y) > 450) { - let ballYSector = ballPos.y/Math.abs(ballPos.y) - return {x: 0, y: ballYSector * 160} - } else { - return {x: 0, y: ballPos.y/2} - } + if (!pos || Vector.size(ballSpeed) < 5 || Math.abs(pos.y) > 300 ) { + // if (Math.abs(ballPos.y) > 450) { + // let ballYSector = ballPos.y/Math.abs(ballPos.y) + // return {x: 0, y: ballYSector * 160} + // } else { + // console.log('2 :', ballPos.y/2) + // return {x: 0, y: ballPos.y/2} + // } } + if (Vector.size(ballSpeed) < 2) { + return ballPos + } + + if (Math.abs(pos.y) > 450 ) { + let ballYSector = ballPos.y/Math.abs(ballPos.y) + return {x: 0, y: ballYSector * 160} + } + return pos } - this.addIntetion(new LineIntention('KeepGoalLine', { - target: {x: -670, y: 0}, - theta: Vector.direction("up"), - lineSize: 1700, - lineDist: 260, - decay: TensorMath.new.finish, - multiplier: BASE_SPEED - })) - this.addIntetion(new LineIntention('followBallProjection', { target: ballProjection, theta: Vector.direction("left"), @@ -54,12 +51,12 @@ module.exports = class GoalkeeperMain extends RulePlays { lineDist: 250, decay: TensorMath.new.finish, multiplier: BASE_SPEED - })) + })) this.addIntetion(new LookAtIntention('LookAtBall', { target: ball, - decay: TensorMath.new.constant(1).finish, - multiplier: 100 + decay: TensorMath.new.pow(1/2).finish, + multiplier: 360 })) } loop(){ diff --git a/players/experimental/GoalkeeperMain2.js b/players/experimental/GoalkeeperMain2.js new file mode 100644 index 0000000..cd66a8d --- /dev/null +++ b/players/experimental/GoalkeeperMain2.js @@ -0,0 +1,66 @@ +const TensorMath = require('../../lib/TensorMath') +const LineIntention = require('../../Intention/LineIntention') +const LookAtIntention = require('../../Intention/LookAtIntention') +const Vector = require('../../lib/Vector') +const RulePlays = require('./RulePlays') + +const BASE_SPEED = 50 +const MAX_SPEED = 80 + +const GOAL_LINE = -650 + +module.exports = class GoalkeeperMain2 extends RulePlays { + setup(){ + super.setup() + let ball = () => { + let ball = { + x: this.frame.cleanData.ball.x, + y: Math.max(Math.min(this.frame.cleanData.ball.y, 200), -200) + } + return ball + } + + // Fixar goleiro na linha do gol + this.addIntetion(new LineIntention('KeepGoalLine', { + target: {x: GOAL_LINE, y: 0}, + theta: Vector.direction("up"), + lineSize: 1700, + lineDist: 260, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * 1.4 + })) + + //Mantem o goleiro fixado na bola, seguindo eixo Y + this.addIntetion(new LineIntention('KeepOnBall', { + target: ball, + theta: Vector.direction("left"), + lineSize: 1700, + lineDist: 80, + decay: TensorMath.new.pow(2).finish, + multiplier: BASE_SPEED + })) + + /* + Correção na função para o goleiro ter mais velocidade + em casos de bola muito proxima do eixo Y + */ + this.addIntetion(new LineIntention('KeepOnBall', { + target: ball, + theta: Vector.direction("left"), + lineSize: 600, + lineDist: 200, + lineDistMax: 200, + decay: TensorMath.new.pow(2).finish, + multiplier: BASE_SPEED * 1.4 + })) + + this.addIntetion(new LookAtIntention('LookAtBall', { + target: ball, + decay: TensorMath.new.pow(1/2).finish, + multiplier: 320 + })) + } + + loop(){ + } +} diff --git a/players/experimental/GoalkeeperPush.js b/players/experimental/GoalkeeperPush.js index d7ce0a1..581e246 100644 --- a/players/experimental/GoalkeeperPush.js +++ b/players/experimental/GoalkeeperPush.js @@ -1,37 +1,13 @@ -const IntentionPlayer = require('../IntentionPlayer') const TensorMath = require('../../lib/TensorMath') const Intention = require('../../Intention') const LineIntention = require('../../Intention/LineIntention') -const PointIntention = require('../../Intention/PointIntention') -const LookAtIntention = require('../../Intention/LookAtIntention') const Vector = require('../../lib/Vector') const RulePlays = require('./RulePlays') const BASE_SPEED = 60 - module.exports = class GoalkeeperPush extends RulePlays { setup(){ super.setup() - let ballProjection = () => { - let pos = this.match.dataManager.ball.projection - let ballSpeed = this.match.dataManager.ball.speed - let ballPos = {x: this.match.dataManager.ball.x, y: this.match.dataManager.ball.y} - /* - A projeção não é usada nos casos onde: - - Não existe vetor projeção (ocorre no primeiro frame de execução) - - Velocidade da bola inferior a 1.2 cm/s (praticamente parada) - - Quando a bola ira bater longe do gol (acima de 30 cm em relação ao centro do gol) - */ - if (!pos || Vector.size(ballSpeed) < 1.2 || Math.abs(pos.y) > 300 ) { - if (Math.abs(ballPos.y) > 450) { - let ballYSector = ballPos.y/Math.abs(ballPos.y) - return {x: 0, y: ballYSector * 160} - } else { - return {x: 0, y: ballPos.y/2} - } - } - return pos - } this.$projectBall = new Intention() diff --git a/players/experimental/GoalkeeperSides.js b/players/experimental/GoalkeeperSides.js index 9b99c99..ebcf3c7 100644 --- a/players/experimental/GoalkeeperSides.js +++ b/players/experimental/GoalkeeperSides.js @@ -7,19 +7,19 @@ const LookAtIntention = require('../../Intention/LookAtIntention') const Vector = require('../../lib/Vector') const RulePlays = require('./RulePlays') -const BASE_SPEED = 45 +const BASE_SPEED = 60 module.exports = class GoalkeeperSides extends RulePlays { setup () { super.setup() let crossbar = () => { - let ballY = this.match.dataManager.ball.y + let ballY = this.frame.cleanData.ball.y let side = ballY/Math.abs(ballY) return {x: -685, y: side * 160} } let ball = () => { - let ball = {x: this.match.dataManager.ball.x, y: this.match.dataManager.ball.y} + let ball = {x: this.frame.cleanData.x, y: this.frame.cleanData.ball.y} return ball } @@ -43,7 +43,7 @@ module.exports = class GoalkeeperSides extends RulePlays { this.addIntetion(new LookAtIntention('LookAtBall', { target: ball, decay: TensorMath.new.constant(1).finish, - multiplier: 85 + multiplier: 35 })) } diff --git a/players/experimental/GoalkeeperSides2.js b/players/experimental/GoalkeeperSides2.js new file mode 100644 index 0000000..5bd3b0f --- /dev/null +++ b/players/experimental/GoalkeeperSides2.js @@ -0,0 +1,44 @@ +const TensorMath = require('../../lib/TensorMath') +const LineIntention = require('../../Intention/LineIntention') +const PointIntention = require('../../Intention/PointIntention') +const Vector = require('../../lib/Vector') +const RulePlays = require('./RulePlays') + +const BASE_SPEED = 40 +const MAX_SPEED = 80 + +const GOAL_LINE = -670 + +module.exports = class GoalkeeperSides2 extends RulePlays { + setup(){ + super.setup() + + let crossbar = () => { + let ballY = this.frame.cleanData.ball.y + let side = ballY/Math.abs(ballY) + return {x: GOAL_LINE - 15, y: side * 160} + } + + // Fixar goleiro na linha do gol + this.addIntetion(new LineIntention('KeepGoalLine', { + target: {x: GOAL_LINE, y: 0}, + theta: Vector.direction("up"), + lineSize: 1700, + lineDist: 260, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED * 1.6 + })) + this.addIntetion(new PointIntention('followCrossBall', { + target: crossbar, + radius: 150, + radiusMax: false, + decay: TensorMath.new.finish, + multiplier: BASE_SPEED + })) + + + } + + loop(){ + } +} diff --git a/players/experimental/MidFieldAttacker.js b/players/experimental/MidFieldAttacker.js index 39ee04b..2b148dd 100644 --- a/players/experimental/MidFieldAttacker.js +++ b/players/experimental/MidFieldAttacker.js @@ -20,14 +20,14 @@ module.exports = class Midfielder extends BaseMidfielder { } let followAttackerShadow = () => { - let pos = this.match.gameManager.coach.attackerRobot.robots.self.position + //let pos = this.match.gameManager.coach.attackerRobot.robots.self.position /* A projeção não é usada nos casos onde: - Não existe vetor projeção (ocorre no primeiro frame de execução) - Velocidade da bola inferior a 1.2 cm/s (praticamente parada) - Quando a bola ira bater longe do gol (acima de 30 cm em relação ao centro do gol) */ - return {x: -250, y: -pos.y/2} + return {x: -250, y: -0/2} } this.addIntetion(new LineIntention('KeepGoalLine', { diff --git a/players/experimental/RulePlays.js b/players/experimental/RulePlays.js index c2acede..9185cc7 100644 --- a/players/experimental/RulePlays.js +++ b/players/experimental/RulePlays.js @@ -8,7 +8,6 @@ const Vector = require('../../lib/Vector') module.exports = class RulePlays extends IntentionPlayer { setup () { - super.setup() this.addIntetion(new LineIntention('avoidFromGoal', { target: {x: 820, y: 0}, theta: Vector.direction("up"), @@ -17,7 +16,7 @@ module.exports = class RulePlays extends IntentionPlayer { lineDistMax: 150, lineDistSingleSide: true, decay: TensorMath.new.mult(-1).finish, - multiplier: 100 + multiplier: 20 })) this.addIntetion(new LineIntention('avoidFromGoalLateral', { @@ -27,7 +26,7 @@ module.exports = class RulePlays extends IntentionPlayer { lineDist: 200, // Tamanho da repelência lineDistMax: 200, decay: TensorMath.new.finish, - multiplier: 100 + multiplier: 20 })) this.addIntetion(new LineIntention('avoidFromOwnGoal', { @@ -38,7 +37,7 @@ module.exports = class RulePlays extends IntentionPlayer { lineDistMax: 120, lineDistSingleSide: true, decay: TensorMath.new.mult(-1).finish, - multiplier: 150 + multiplier: 25 })) this.addIntetion(new LineIntention('avoidFromGoalOwnLateral', { @@ -48,7 +47,7 @@ module.exports = class RulePlays extends IntentionPlayer { lineDist: 200, // Tamanho da repelência lineDistMax: 200, decay: TensorMath.new.finish, - multiplier: 150 + multiplier: 15 })) } loop () {} diff --git a/players/tests/LineIntentionPlayer.js b/players/tests/LineIntentionPlayer.js index 7f665f0..460b1d2 100644 --- a/players/tests/LineIntentionPlayer.js +++ b/players/tests/LineIntentionPlayer.js @@ -1,9 +1,6 @@ const IntentionPlayer = require('../IntentionPlayer') const TensorMath = require('../../lib/TensorMath') -const Intention = require('../../Intention') const LineIntention = require('../../Intention/LineIntention') -const PointIntention = require('../../Intention/PointIntention') -const LookAtIntention = require('../../Intention/LookAtIntention') const Vector = require('../../lib/Vector') const FORWARD_SPEED = 50 @@ -11,10 +8,11 @@ const FORWARD_SPEED = 50 module.exports = class LineIntentionPlayer extends IntentionPlayer { setup(){ this.addIntetion(new LineIntention('test', { - target: {x: 100, y: 100}, - theta: Vector.direction("left"), + target: {x: 0, y: 0}, + theta: Vector.direction("up"), lineSize: 1700, lineDist: 260, + lineDistMax: 400, decay: TensorMath.new.finish, multiplier: FORWARD_SPEED })) diff --git a/players/tests/LookAtIntentionPlayer.js b/players/tests/LookAtIntentionPlayer.js index f81b81a..9da8239 100644 --- a/players/tests/LookAtIntentionPlayer.js +++ b/players/tests/LookAtIntentionPlayer.js @@ -1,12 +1,8 @@ const IntentionPlayer = require('../IntentionPlayer') const TensorMath = require('../../lib/TensorMath') -const Intention = require('../../Intention') -const LineIntention = require('../../Intention/LineIntention') -const PointIntention = require('../../Intention/PointIntention') const LookAtIntention = require('../../Intention/LookAtIntention') -const Vector = require('../../lib/Vector') -const FORWARD_SPEED = 80 +const FORWARD_SPEED = 480 module.exports = class LookAtIntentionPlayer extends IntentionPlayer { setup(){ @@ -14,7 +10,7 @@ module.exports = class LookAtIntentionPlayer extends IntentionPlayer { this.addIntetion(new LookAtIntention('test', { target: ball, - decay: TensorMath.new.constant(1).finish, + decay: TensorMath.new.pow(1/2).finish, multiplier: FORWARD_SPEED, })) } diff --git a/players/tests/PointIntentionPlayer.js b/players/tests/PointIntentionPlayer.js index bfc999d..3b7eac9 100644 --- a/players/tests/PointIntentionPlayer.js +++ b/players/tests/PointIntentionPlayer.js @@ -1,20 +1,19 @@ const IntentionPlayer = require('../IntentionPlayer') const TensorMath = require('../../lib/TensorMath') -const Intention = require('../../Intention') -const LineIntention = require('../../Intention/LineIntention') const PointIntention = require('../../Intention/PointIntention') -const LookAtIntention = require('../../Intention/LookAtIntention') const Vector = require('../../lib/Vector') -const FORWARD_SPEED = 50 +const FORWARD_SPEED = 80 module.exports = class PointIntentionPlayer extends IntentionPlayer { setup(){ + let ball = () => {return this.ball} + this.addIntetion(new PointIntention('test', { - target: {x: 0, y: 0}, + target: ball, theta: Vector.direction("left"), - radius: 100, - decay: TensorMath.new.finish, + radius: 400, + decay: TensorMath.new.pow(1.35).finish, multiplier: FORWARD_SPEED })) } diff --git a/roles/AttackerRole.js b/roles/AttackerRole.js new file mode 100644 index 0000000..a3b9448 --- /dev/null +++ b/roles/AttackerRole.js @@ -0,0 +1,71 @@ +const AttackerMain = require('../players/experimental/AttackerMain') +const AttackerConduct = require('../players/experimental/AttackerConduct') +const AttackerHold = require('../players/experimental/AttackerHold') +const attackerTriangle = require('../players/experimental/AttackerTriangle') +const { SMALL_AREA, GP } = require('../entities/FieldConstraints') + + +module.exports = class AttackerRole { + constructor(match) { + this.match = match + this.init() + } + + async init() { + this.plays = { + main: new AttackerMain(0, this.match, null), + conduct: new AttackerConduct(0, this.match, null), + hold: new AttackerHold(0, this.match, null), + triangle: new attackerTriangle(0, this.match, null) + } + } + + insideFieldConstraint (fieldConstraint, ball) { + if (ball == null) return false + if (ball.x > fieldConstraint.x0 && ball.x < fieldConstraint.x1 + && ball.y > fieldConstraint.y0 && ball.y < fieldConstraint.y1) return true + return false + } + + buildTriangle (robot) { + return { + x1: GP.x, + y1: GP.y - 100, + x2: GP.x, + y2: -GP.y + 100, + + x3: robot.robots.self.position.x, + y3: robot.robots.self.position.y + } + } + + isInsideTriangle (robot, ball) { + const { x1, x2, x3, y1, y2, y3 } = this.buildTriangle(robot) + const { x, y } = ball + + var denominator = ((y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3)); + var a = ((y2 - y3)*(x - x3) + (x3 - x2)*(y - y3)) / denominator; + var b = ((y3 - y1)*(x - x3) + (x1 - x3)*(y - y3)) / denominator; + var c = 1 - a - b; + + return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1; + } + + decidePlay(robot, data) { + let position = robot.robots.self.position + let ball = data.cleanData.ball + + if (this.isInsideTriangle(robot, ball)) { + robot.runningPlay = this.plays.triangle + this.plays.triangle.setRobot(robot) + } else if (this.insideFieldConstraint(SMALL_AREA, ball)) { + robot.runningPlay = this.plays.hold + this.plays.hold.setRobot(robot) + } else { + robot.runningPlay = this.plays.main + this.plays.main.setRobot(robot) + } + + console.log('|robot' + robot.radioId + '| decided play: ' + robot.runningPlay.constructor.name) + } +} diff --git a/roles/GoalkeeperRole.js b/roles/GoalkeeperRole.js new file mode 100644 index 0000000..e5c889c --- /dev/null +++ b/roles/GoalkeeperRole.js @@ -0,0 +1,51 @@ +const GoalKeeperMain = require('../players/experimental/GoalkeeperMain2') +const GoalKeeperSides = require('../players/experimental/GoalkeeperSides2') +const GoalKeeperPush = require('../players/experimental/GoalKeeperPush2') +const GoalKeeperKeep = require('../players/experimental/GoalKeeperKeep') +const FieldConstraints = require('../entities/FieldConstraints') + + +module.exports = class GoalKeeperRole { + constructor(match) { + this.match = match + this.init() + } + + async init() { + this.plays = { + main: new GoalKeeperMain(0, this.match, null), + sides: new GoalKeeperSides(0, this.match, null), + push: new GoalKeeperPush(0, this.match, null), + keep: new GoalKeeperKeep(0, this.match, null) + } + } + + insideFieldConstraint (fieldConstraint, ball) { + if (ball == null) return false + if (ball.x > fieldConstraint.x0 && ball.x < fieldConstraint.x1 + && ball.y > fieldConstraint.y0 && ball.y < fieldConstraint.y1) return true + return false + } + + decidePlay(robot, data) { + + const ball = data.cleanData.ball + if( + this.insideFieldConstraint(FieldConstraints.SMALL_AREA, ball) + ){ + robot.runningPlay = this.plays.push + this.plays.push.setRobot(robot) + } else if ( + this.insideFieldConstraint(FieldConstraints.LEFT, ball) + || this.insideFieldConstraint(FieldConstraints.RIGHT, ball) + ) { + robot.runningPlay = this.plays.sides + this.plays.sides.setRobot(robot) + } else{ + robot.runningPlay = this.plays.main + this.plays.main.setRobot(robot) + } + + console.log('|robot' + robot.radioId + '| decided play: ' + robot.runningPlay.constructor.name) + } +} diff --git a/roles/_GoalkeeperRole.js b/roles/_GoalkeeperRole.js new file mode 100644 index 0000000..09957bc --- /dev/null +++ b/roles/_GoalkeeperRole.js @@ -0,0 +1,64 @@ +const GoalKeeper = require('../players/experimental/GoalkeeperMain') +const GoalKeeperSides = require('../players/experimental/GoalkeeperSides') +const GoalKeeperPush = require('../players/experimental/GoalkeeperPush') +const FieldConstraints = require('../entities/FieldConstraints') + + +module.exports = class _GoalKeeperRole { + constructor(match) { + this.match = match + this.init() + } + + async init() { + this.plays = { + main: new GoalKeeper(0, this.match, null), + push: new GoalKeeperPush(0, this.match, null), + side: new GoalKeeperSides(0, this.match, null) + } + } + + insideFieldConstraint (fieldConstraint, ball) { + if (ball == null) return false + if (ball.x > fieldConstraint.x0 && ball.x < fieldConstraint.x1 + && ball.y > fieldConstraint.y0 && ball.y < fieldConstraint.y1) return true + return false + } + + decidePlay(robot, data) { + /* + O Goleiro tem 4 tipos de comportamentos bem definidos: + + 1: Se não houver bola em campo então goleiro fica no centro do gol (play main) + 2: Se a bola estiver dentro da pequena area, empurre a bola para longe (play push) + 3: Se a bola estiver nas laterais da pequena area, proteja a trave mais proxima (play sides) + 4: caso contrario, fique no centro do gol (play main) + */ + let ball = null + if (data) + ball = data.cleanData.ball || null + if (!ball) { + robot.runningPlay = this.plays.main + this.plays.main.setRobot(robot) + } + if (this.insideFieldConstraint(FieldConstraints.SMALL_AREA_CENTER, ball)) { + robot.runningPlay = this.plays.push + this.plays.push.setRobot(robot) + } else if ( + this.insideFieldConstraint(FieldConstraints.SMALL_AREA_LEFT, ball) + || + this.insideFieldConstraint(FieldConstraints.SMALL_AREA_RIGHT, ball) + ) { + robot.runningPlay = this.plays.side + this.plays.side.setRobot(robot) + } else { + robot.runningPlay = this.plays.main + this.plays.main.setRobot(robot) + } + + robot.runningPlay = this.plays.main + this.plays.main.setRobot(robot) + + console.log('|robot' + robot.radioId + '| decided play: ' + robot.runningPlay.constructor.name) + } +} \ No newline at end of file diff --git a/lib/Constants.js b/roles/attacker.js similarity index 100% rename from lib/Constants.js rename to roles/attacker.js diff --git a/server.js b/server.js index 42f4c5e..d36233d 100644 --- a/server.js +++ b/server.js @@ -8,18 +8,13 @@ const Match = require('./lib/Match') const TAG = 'server' -const RUN_MODES = {1: 'REAL_LIFE', 2: 'SIMPLE_SIMULATED', 3: 'SIMULATED', 4: 'PASSIVE'} +const RUN_MODES = { + 1: 'REAL_LIFE', 2: 'SIMPLE_SIMULATED', + 3: 'SIMULATED', 4: 'PASSIVE' +} -/* -Variavel RUN_MODE args: - 1: REAL_LIFE, Executa o fluxo completo, usado para partidas reais - 2: SIMPLE_SIMULATED, modo simulado, apenas movimentando a posição dos robos sem fisica - 3: SIMULATED, modo simulado, usando stack SIR-LAB - 4: PASSIVE , modo assistido, onde o NoPlan recebe dados do - SSL-Vision mas não envia para lugar algum -*/ const run_mode = parseInt(process.env.RUN_MODE) - +console.log(run_mode) assert.notEqual(run_mode, null, chalk.red('MISSING PARAMETER: RUN_MODE')) assert.ok(run_mode in RUN_MODES, chalk.red('WRONG PARAMETER: RUN_MODE, must be 1, 2 or 3')) @@ -32,7 +27,7 @@ async function startup(){ let driverImpl = null let MatchClass = Match - let CoachClass = require('./lib/Coach') + let CoachClass = require('./lib/DumbCoach') switch (run_mode) { case 1: @@ -62,12 +57,22 @@ async function startup(){ // Driver: dados referentes ao output de dados de envio para os robos vision: {impl: visionImpl, params: config[visionImpl]}, driver: {impl: driverImpl, params: config[driverImpl]}, - coach: CoachClass, - robotsProperties: { - robot_1: {vision_id: 9, radio_id: 1}, - robot_2: {vision_id: 1, radio_id: 2}, - robot_3: {vision_id: 3, radio_id: 3} + coaches: [CoachClass, CoachClass], + matchParams: { + 'startSide': config.startSide, + 'startColor': config.startColor }, + robotsProperties:[ + { + // TEAM 1 + robot_2: {vision_id: 1, radio_id: 3}, + robot_3: {vision_id: 9, radio_id: 2}, + robot_1: {vision_id: 3, radio_id: 1} + }, + { + + } + ] }) await match.init() @@ -76,10 +81,10 @@ async function startup(){ } -process.on('unhandledRejection', (e) => { - console.error('Unhandled Rejection') - console.error(e) - process.exit(1) -}) +// process.on('unhandledRejection', (e) => { +// console.error('Unhandled Rejection') +// console.error(e) +// process.exit(1) +// }) startup()