<commit_before>/*
This is a game by:
Markus "TiByte" Becker   - Lead Developer
Lucas "LFalch"           - Programmer
Aileen                   - Graphic Designer
Kilian "Malloth Rha"     - Musician
Micha                    - Junior Programmer
Using Libraries: Pixi.js and Howler.js
date: 16.04.2016 for LD35
theme: Shapeshift
*/

/*

STRING OF EVENTS:
1. Intro Comic (3 Pictures)
    - socks come to life when unattended
2. Under the bed
    2.1. game
        - avoid hands
    2.2. more story
        - grey sock tells hero to fight sewer monster
3. Sewerfall
    3.1. game
        - falling in the sewer
        - avoid dirt
    3.2. reward (grow arms)
        - if not too dirty
4. Snake game
    4.1. game
        - eat fluff
    4.2. reward (grow bigger)
        - if player ate more than 20 fluff in 30 sec.
5. Plumbing game
    5.1. game
        - turn tiles to connect pipes
    5.2. reward (grow hair)
        - did it in 15 seconds
### Optional ###
0. Platforming game
    0.1. game
    0.2. reward (grow wings)
################
6. Doodle Jump
    6.1. game
        - collect something to gain height
    6.2. more story
        - if won grabbed by sock-hand
        - else falling = losing health
7. Boss fight
    - attack in turns
*/

// Cheat Sheet: https://github.com/mtib/ludum34/blob/master/game.js

// Canvas Size
const WIDTH = 1280;
const HEIGHT = 720;

// Current version
const version = "0.01d"

// Initialize Renderer
var renderer = PIXI.autoDetectRenderer(WIDTH, HEIGHT, {antialiasing: true, transparent: false, resolution: 1});
renderer.backgroundColor = 0x6ec2cb;
document.getElementById("gamediv").appendChild(renderer.view);

// Master Containter
var stage = new PIXI.Container();

// Layers
var cBack = new PIXI.Container();
var cMiddle = new PIXI.Container();
var cFront = new PIXI.Container();
var cGui = new PIXI.Container();

// Config goes here:
const fontConfig = {font: "30px 'Arial'", fill: "#000000", align: "left"};
const debugConfig = {font: "20px 'Fira Code',monospace,sans-serif", fill: "#FF0000", align: "left"};
const relcenter = {x:0.5,y:0.5};
const nKey = keyboard(78);
const enterKey = keyboard(13);

const leftArrow = keyboard(37);
const upArrow = keyboard(38);
const rightArrow = keyboard(39);
const downArrow = keyboard(40);

const aKey = keyboard(65);
const wKey = keyboard(87);
const dKey = keyboard(68);
const sKey = keyboard(83);

const s001bg = "./scenes/001/background.jpg"; // background for game #1
const ssock = "./scenes/001/sock.png"; // normal sock, for use in all? scenes
const s001armo = "./scenes/001/arm.open.png"; // o = open
const s001armg = "./scenes/001/arm.sock.png"; // g = grabbed

function Game1Sock() {
    self = this;
    size = 128 // Pixel
    speed = 3 // Pixel / Frame
    this.sprite = new PIXI.Sprite.fromImage(ssock);
    this.sprite.anchor = relcenter;
    this.sprite.width = size;
    this.sprite.height = size;
    this.sprite.position = {x: WIDTH*0.5, y: HEIGHT*0.5};
    this.die = function() {
        cMiddle.removeChild(this.sprite);
    }
    this.move = function() {
        delta = {x:0, y:0};
        did = false;
        if ((rightArrow.isDown || dKey.isDown) && this.sprite.position.x < WIDTH - 70) {
            delta.x += speed;
        }
        if ((leftArrow.isDown || aKey.isDown) && this.sprite.position.x > 70) {
            delta.x -= speed;
        }
        if ((upArrow.isDown || wKey.isDown) && this.sprite.position.y > 230) {
            delta.y -= speed;
        }
        if ((downArrow.isDown || sKey.isDown) && this.sprite.position.y < HEIGHT - 100) {
            delta.y += speed;
        }
        magsqr = Math.sqrt(Math.abs(delta.x) + Math.abs(delta.y))
        if (magsqr == 0) {
            return;
        }
        if (delta.x > 0 && this.sprite.scale.x > 0) {
            this.sprite.scale.x *= -1;
        } else if (delta.x < 0 && this.sprite.scale.x < 0) {
            this.sprite.scale.x *= -1;
        }
        delta.x /= magsqr;
        delta.y /= magsqr;
        this.sprite.position.x += delta.x;
        this.sprite.position.y += delta.y;
    }
    cMiddle.addChild(this.sprite);
    console.log("stuff should happen");
}

function State() {
    self = this;
    this.debugText = new PIXI.Text("Version: "+version+"\n<Debug Information>",debugConfig);
    this.debugText.position = {x:5,y:5};
    this.debugStateText = new PIXI.Text("State: 0", debugConfig);
    this.debugStateText.position = {x:5,y:45};

    this.doc = {}; // DestroyOnChange

    cGui.addChild(this.debugText);
    cGui.addChild(this.debugStateText);
    this.number = 0;
    this.run = function(){
        console.log("default state");
    }

    this.nextState = function(){
        for (var sprite in this.doc) {
            if (this.doc.hasOwnProperty(sprite)) {
                if (this.doc[sprite].die) {
                    this.doc[sprite].die();
                } else {
                    cBack.removeChild(this.doc[sprite]);
                }
            }
        }
        this.number += 1;
        this.switched = true;
        this.debugStateText.text = "State: " + this.number;
        this.run = this.funcarray[this.number];
    }
    this.introfunc = function(){
        console.log("intro func");
        if (nKey.isDown){
            this.nextState();
        }
    }
    this.switched = true;
    this.underTheBed = function(){
        if (this.switched) {
            this.doc["s001bg"] = PIXI.Sprite.fromImage(s001bg);
            this.doc["s001armo"] = PIXI.Sprite.fromImage(s001armo);
            this.doc["s001armg"] = PIXI.Sprite.fromImage(s001armg);

            this.doc["s001bg"].width = WIDTH;
            this.doc["s001bg"].height = HEIGHT;
            cBack.addChild(this.doc["s001bg"]);
            this.doc["gamesock"] = new Game1Sock();

            this.switched = false;
        }
        this.doc["gamesock"].move();
    }
    this.funcarray = [this.introfunc, this.underTheBed];

    this.run = this.funcarray[this.number];
}

var gamestate = new State();

/*
    stage
      |
      +-- cBack
      +-- cMiddle
      +-- cFront
      +-- cGui
Drawn from top to bottom
*/
stage.addChild(cBack);
stage.addChild(cMiddle);
stage.addChild(cFront);
stage.addChild(cGui);

PIXI.loader
    .add(s001bg)
    .add(s001armg)
    .add(s001armo)
    .add(ssock)
    .load(setup);

function setup(){
    // Do setup here
    // Easteregg: eyes!¬
    renderStage();
}

// Request Animation Frame
function renderStage(){
    requestAnimationFrame(renderStage);
    gameLoop();
    renderer.render(stage);
}

// Called before rendering
function gameLoop(){
    // after doing logic:
    gamestate.run()
}

// start game
setup();
<commit_msg>Add intro state<commit_after>/*
This is a game by:
Markus "TiByte" Becker   - Lead Developer
Lucas "LFalch"           - Programmer
Aileen                   - Graphic Designer
Kilian "Malloth Rha"     - Musician
Micha                    - Junior Programmer
Using Libraries: Pixi.js and Howler.js
date: 16.04.2016 for LD35
theme: Shapeshift
*/

/*

STRING OF EVENTS:
1. Intro Comic (3 Pictures)
    - socks come to life when unattended
2. Under the bed
    2.1. game
        - avoid hands
    2.2. more story
        - grey sock tells hero to fight sewer monster
3. Sewerfall
    3.1. game
        - falling in the sewer
        - avoid dirt
    3.2. reward (grow arms)
        - if not too dirty
4. Snake game
    4.1. game
        - eat fluff
    4.2. reward (grow bigger)
        - if player ate more than 20 fluff in 30 sec.
5. Plumbing game
    5.1. game
        - turn tiles to connect pipes
    5.2. reward (grow hair)
        - did it in 15 seconds
### Optional ###
0. Platforming game
    0.1. game
    0.2. reward (grow wings)
################
6. Doodle Jump
    6.1. game
        - collect something to gain height
    6.2. more story
        - if won grabbed by sock-hand
        - else falling = losing health
7. Boss fight
    - attack in turns
*/

// Cheat Sheet: https://github.com/mtib/ludum34/blob/master/game.js

// Canvas Size
const WIDTH = 1280;
const HEIGHT = 720;

// Current version
const version = "0.01d"

// Initialize Renderer
var renderer = PIXI.autoDetectRenderer(WIDTH, HEIGHT, {antialiasing: true, transparent: false, resolution: 1});
renderer.backgroundColor = 0x6ec2cb;
document.getElementById("gamediv").appendChild(renderer.view);

// Master Containter
var stage = new PIXI.Container();

// Layers
var cBack = new PIXI.Container();
var cMiddle = new PIXI.Container();
var cFront = new PIXI.Container();
var cGui = new PIXI.Container();

// Config goes here:
const fontConfig = {font: "30px 'Arial'", fill: "#000000", align: "left"};
const debugConfig = {font: "20px 'Fira Code',monospace,sans-serif", fill: "#FF0000", align: "left"};
const relcenter = {x:0.5,y:0.5};
const nKey = keyboard(78);
const enterKey = keyboard(13);

const leftArrow = keyboard(37);
const upArrow = keyboard(38);
const rightArrow = keyboard(39);
const downArrow = keyboard(40);

const aKey = keyboard(65);
const wKey = keyboard(87);
const dKey = keyboard(68);
const sKey = keyboard(83);

const s000bed1 = "./scenes/000/bed.pic1.jpg";
const s000bed2 = "./scenes/000/bed.pic2.jpg";
const s001bg = "./scenes/001/background.jpg"; // background for game #1
const ssock = "./scenes/001/sock.png"; // normal sock, for use in all? scenes
const s001armo = "./scenes/001/arm.open.png"; // o = open
const s001armg = "./scenes/001/arm.sock.png"; // g = grabbed

function Game1Sock() {
    self = this;
    size = 128 // Pixel
    speed = 3 // Pixel / Frame
    this.sprite = new PIXI.Sprite.fromImage(ssock);
    this.sprite.anchor = relcenter;
    this.sprite.width = size;
    this.sprite.height = size;
    this.sprite.position = {x: WIDTH*0.5, y: HEIGHT*0.5};
    this.die = function() {
        cMiddle.removeChild(this.sprite);
    }
    this.move = function() {
        delta = {x:0, y:0};
        did = false;
        if ((rightArrow.isDown || dKey.isDown) && this.sprite.position.x < WIDTH - 70) {
            delta.x += speed;
        }
        if ((leftArrow.isDown || aKey.isDown) && this.sprite.position.x > 70) {
            delta.x -= speed;
        }
        if ((upArrow.isDown || wKey.isDown) && this.sprite.position.y > 230) {
            delta.y -= speed;
        }
        if ((downArrow.isDown || sKey.isDown) && this.sprite.position.y < HEIGHT - 100) {
            delta.y += speed;
        }
        magsqr = Math.sqrt(Math.abs(delta.x) + Math.abs(delta.y))
        if (magsqr == 0) {
            return;
        }
        if (delta.x > 0 && this.sprite.scale.x > 0) {
            this.sprite.scale.x *= -1;
        } else if (delta.x < 0 && this.sprite.scale.x < 0) {
            this.sprite.scale.x *= -1;
        }
        delta.x /= magsqr;
        delta.y /= magsqr;
        this.sprite.position.x += delta.x;
        this.sprite.position.y += delta.y;
    }
    cMiddle.addChild(this.sprite);
    console.log("stuff should happen");
}

function State() {
    self = this;
    this.debugText = new PIXI.Text("Version: "+version+"\n<Debug Information>\nState: ",debugConfig);
    this.debugText.position = {x:5,y:5};
    this.debugStateText = new PIXI.Text("0", debugConfig);
    this.debugStateText.position = {x:89,y:45};

    this.doc = {}; // DestroyOnChange

    cGui.addChild(this.debugText);
    cGui.addChild(this.debugStateText);
    this.number = 0;
    this.run = function(){
        console.log("default state");
    }

    this.nextState = function(){
        for (var sprite in this.doc) {
            if (this.doc.hasOwnProperty(sprite)) {
                if (this.doc[sprite].die) {
                    this.doc[sprite].die();
                } else {
                    cBack.removeChild(this.doc[sprite]);
                }
            }
        }
        this.number += 1;
        this.switched = true;
        this.debugStateText.text = this.number;
        this.run = this.funcarray[this.number];
    }
    this.substate = 0;
    this.introfunc = function(){
        if (this.switched){
            this.substate = 1;
            this.doc["s000bed1"] = PIXI.Sprite.fromImage(s000bed1);
            this.doc["s000bed2"] = PIXI.Sprite.fromImage(s000bed2);

            this.doc["s000bed1"].width = WIDTH;
            this.doc["s000bed1"].height = HEIGHT;
            this.doc["s000bed2"].width = WIDTH;
            this.doc["s000bed2"].height = HEIGHT;

            cBack.addChild(this.doc["s000bed1"]);

            this.switched = false;
        }
    }
    nKey.press = function(){
        console.log(self.number, self.substate);
        if (self.number === 0){
            if (self.substate == 2){
                self.nextState();
            }else{
                cBack.removeChild(self.doc["s000bed"+self.substate++]);
                cBack.addChild(self.doc["s000bed"+self.substate]);
            }
        }
    }
    this.switched = true;
    this.underTheBed = function(){
        if (this.switched) {
            this.doc["s001bg"] = PIXI.Sprite.fromImage(s001bg);
            this.doc["s001armo"] = PIXI.Sprite.fromImage(s001armo);
            this.doc["s001armg"] = PIXI.Sprite.fromImage(s001armg);

            this.doc["s001bg"].width = WIDTH;
            this.doc["s001bg"].height = HEIGHT;
            cBack.addChild(this.doc["s001bg"]);
            this.doc["gamesock"] = new Game1Sock();

            this.switched = false;
        }
        this.doc["gamesock"].move();
    }
    this.funcarray = [this.introfunc, this.underTheBed];

    this.run = this.funcarray[this.number];
}

var gamestate = new State();

/*
    stage
      |
      +-- cBack
      +-- cMiddle
      +-- cFront
      +-- cGui
Drawn from top to bottom
*/
stage.addChild(cBack);
stage.addChild(cMiddle);
stage.addChild(cFront);
stage.addChild(cGui);

PIXI.loader
    .add(s001bg)
    .add(s001armg)
    .add(s001armo)
    .add(ssock)
    .load(setup);

function setup(){
    // Do setup here
    // Easteregg: eyes!¬
    renderStage();
}

// Request Animation Frame
function renderStage(){
    requestAnimationFrame(renderStage);
    gameLoop();
    renderer.render(stage);
}

// Called before rendering
function gameLoop(){
    // after doing logic:
    gamestate.run()
}

// start game
setup();
<|endoftext|>


<commit_before>var Game = require('crtrdg-gameloop')
var Keyboard = require('crtrdg-keyboard')
var Player = require('./entity/player.js')
var Camera = require('./entity/camera.js')
var World = require('./entity/world.js')
var Ring = require('./entity/ring.js')
var Mask = require('./util/mask.js')

module.exports = function (canvas, schema, opts) {
  opts = opts || {}

  var game = new Game({
    canvas: canvas,
    width: opts.width,
    height: opts.height
  })

  var keyboard = new Keyboard(game)

  var player = new Player({
    character: schema.players[0].character,
    translation: schema.players[0].translation,
    scale: 2,
    speed: {translation: 1, rotation: 8},
    friction: 0.9,
    stroke: 'white',
    fill: 'rgb(75,75,75)',
    thickness: 0.5
  })

  var camera = new Camera({
    scale: 0.1,
    speed: {translation: 0.1, rotation: 0.1, scale: 0.002},
    friction: 0.9,
    yoked: true
  })

  var ring = new Ring({
    size: 0.82 * game.width / 2,
    translation: [game.width / 2, game.width / 2],
    extent: 0.1 * game.width / 2,
    count: 8,
    offset: 3
  })

  var mask = new Mask({
    size: 0.8 * game.width / 2,
    translation: [game.width / 2, game.width / 2],
    fill: 'rgb(90,90,90)'
  })

  var world = new World(schema.tiles, {thickness: 0.25})

  player.addTo(game)
  camera.addTo(game)
  world.addTo(game)
  ring.addTo(game)

  keyboard.on('keydown', function (keyCode) {
    if (keyCode === '<space>') {
      if (game.ticker.paused === true) {
        game.resume()
      } else {
        game.pause()
      }
    }
  })

  player.on('update', function (interval) {
    this.move(keyboard, world)
  })

  camera.on('update', function (interval) {
    if (camera.yoked) {
      camera.transform.translation = player.geometry.transform.translation
      camera.transform.rotation = player.geometry.transform.rotation
    }
    this.move(keyboard)
  })

  ring.on('update', function (interval) {
    this.update(player, world)
  })

  game.on('draw', function (context) {
    mask.set(context)
    world.draw(context, camera)
    player.draw(context, camera)
    mask.unset(context)
    ring.draw(context)
  })

  return {
    reload: function (schema) {
      world = new World(schema, {thickness: 0.25})
    },

    pause: function () {
      game.pause()
    },

    resume: function () {
      game.resume()
    }
  }
}
<commit_msg>Fix reload<commit_after>var Game = require('crtrdg-gameloop')
var Keyboard = require('crtrdg-keyboard')
var Player = require('./entity/player.js')
var Camera = require('./entity/camera.js')
var World = require('./entity/world.js')
var Ring = require('./entity/ring.js')
var Mask = require('./util/mask.js')

module.exports = function (canvas, schema, opts) {
  opts = opts || {}

  var game = new Game({
    canvas: canvas,
    width: opts.width,
    height: opts.height
  })

  var keyboard = new Keyboard(game)

  var player = new Player({
    character: schema.players[0].character,
    translation: schema.players[0].translation,
    scale: 2,
    speed: {translation: 1, rotation: 8},
    friction: 0.9,
    stroke: 'white',
    fill: 'rgb(75,75,75)',
    thickness: 0.5
  })

  var camera = new Camera({
    scale: 0.1,
    speed: {translation: 0.1, rotation: 0.1, scale: 0.002},
    friction: 0.9,
    yoked: true
  })

  var ring = new Ring({
    size: 0.82 * game.width / 2,
    translation: [game.width / 2, game.width / 2],
    extent: 0.1 * game.width / 2,
    count: 8,
    offset: 3
  })

  var mask = new Mask({
    size: 0.8 * game.width / 2,
    translation: [game.width / 2, game.width / 2],
    fill: 'rgb(90,90,90)'
  })

  var world = new World(schema.tiles, {thickness: 0.25})

  player.addTo(game)
  camera.addTo(game)
  world.addTo(game)
  ring.addTo(game)

  keyboard.on('keydown', function (keyCode) {
    if (keyCode === '<space>') {
      if (game.ticker.paused === true) {
        game.resume()
      } else {
        game.pause()
      }
    }
  })

  player.on('update', function (interval) {
    this.move(keyboard, world)
  })

  camera.on('update', function (interval) {
    if (camera.yoked) {
      camera.transform.translation = player.geometry.transform.translation
      camera.transform.rotation = player.geometry.transform.rotation
    }
    this.move(keyboard)
  })

  ring.on('update', function (interval) {
    this.update(player, world)
  })

  game.on('draw', function (context) {
    mask.set(context)
    world.draw(context, camera)
    player.draw(context, camera)
    mask.unset(context)
    ring.draw(context)
  })

  return {
    reload: function (schema) {
      world = new World(schema.tiles, {thickness: 0.25})
    },

    pause: function () {
      game.pause()
    },

    resume: function () {
      game.resume()
    }
  }
}
<|endoftext|>


<commit_before>var Hoops = {
    showDebug: false
};

Hoops.Preloader = function () {};

Hoops.Preloader.prototype = {

    init: function () {

        this.input.maxPointers = 1;

        this.scale.pageAlignHorizontally = true;

        this.physics.startSystem(Phaser.Physics.P2JS);

    },

    preload: function () {

        this.load.path = 'assets/';

        this.load.atlas('player');

        this.load.physics('basket');

        this.load.bitmapFont('fat-and-tiny');

        this.load.images([ 'logo', 'ball', 'basket', 'board' ]);

    },

    create: function () {

        this.state.start('Hoops.MainMenu');

    }

};

Hoops.MainMenu = function () {};

Hoops.MainMenu.prototype = {

    create: function () {

        this.stage.backgroundColor = 0x001133;

        var logo = this.add.image(this.world.centerX, 80, 'logo');
        logo.anchor.x = 0.5;

        var start = this.add.bitmapText(this.world.centerX, 460, 'fat-and-tiny', 'CLICK TO PLAY ;) ', 64);
        start.anchor.x = 0.5;
        start.smoothed = false;

        this.input.onDown.addOnce(this.start, this);

    },

    start: function () {

        this.state.start('Hoops.Game');

    }

};

Hoops.Game = function () {

    this.score = 0;
    this.scoreText = null;

    this.shotsLeft = 20;
    this.shotsLeftText = null;

    this.player1 = null;
    this.player2 = null;
    this.player3 = null;
    this.player4 = null;
    this.player5 = null;

    this.balls = null;

    this.board = null;
    this.basket = null;

    this.boardSpeed = 80;

    this.pauseKey = null;
    this.debugKey = null;

};

Hoops.Game.prototype = {

    init: function () {

        this.physics.p2.gravity.y = 300;
        this.physics.p2.restitution = 0.8;

        this.score = 0;
        this.shotsLeft = 20;

    },

    create: function () {

        this.stage.backgroundColor = 0xDC143C;

        this.board = this.add.sprite(700, 200, 'board');

        this.physics.p2.enable(this.board, Hoops.showDebug);

        this.board.body.static = true;
        this.board.body.clearShapes();
        this.board.body.loadPolygon('basket', 'basket');

        var circle = this.board.body.addCircle(12, 0, 90);
        circle.sensor = true;

        this.board.body.data.gravityScale = 0;
        this.board.body.velocity.x = this.boardSpeed;

        this.board.body.onBeginContact.add(this.checkBall, this);

        this.balls = this.add.physicsGroup(Phaser.Physics.P2JS);
        this.balls.enableBodyDebug = Hoops.showDebug;

        this.basket = this.add.sprite(100, 400, 'basket');
        this.basket.anchor.set(0.5);

        this.player1 = this.add.sprite(60, 430, 'player', 'player1down');
        this.player2 = this.add.sprite(190, 410, 'player', 'player2down');
        this.player3 = this.add.sprite(320, 390, 'player', 'player3down');
        this.player4 = this.add.sprite(450, 410, 'player', 'player4down');
        this.player5 = this.add.sprite(580, 430, 'player', 'player5down');

        for (var i = 1; i <= 5; i++)
        {
            this['player' + i].name = i;
            this['player' + i].inputEnabled = true;
            this['player' + i].events.onInputDown.add(this.shoot, this);
        }

        //  Score
        this.scoreText = this.add.bitmapText(16, 0, 'fat-and-tiny', 'SCORE: 0', 32);
        this.scoreText.smoothed = false;

        this.shotsLeftText = this.add.bitmapText(660, 0, 'fat-and-tiny', 'SHOTS: ' + this.shotsLeft, 32);
        this.shotsLeftText.smoothed = false;

        //  Press P to pause and resume the game
        this.pauseKey = this.input.keyboard.addKey(Phaser.Keyboard.P);
        this.pauseKey.onDown.add(this.togglePause, this);

        //  Press D to toggle the debug display
        this.debugKey = this.input.keyboard.addKey(Phaser.Keyboard.D);
        this.debugKey.onDown.add(this.toggleDebug, this);

    },

    togglePause: function () {

        this.game.paused = (this.game.paused) ? false : true;

    },

    toggleDebug: function () {

        Hoops.showDebug = (Hoops.showDebug) ? false : true;

        this.state.restart();

    },

    checkBall: function (body, bodyB, shapeA, shapeB, equation) {

        if (shapeA.type === 1 && shapeB.type === 1)
        {
            //  We've got 2 circles, work out which one is the sensor
            var ball = shapeA.body;

            if (shapeA.sensor)
            {
                ball = shapeB.body;
            }

            if (ball.velocity[1] > 0)
            {
                //  Ball is going UP through the net, so it's a foul
                ball.parent.sprite.foul = true;
            }
            else
            {
                if (!ball.parent.sprite.foul)
                {
                    this.score++;
                    this.scoreText.text = "SCORE: " + this.score;
                }
            }
        }

    },

    shoot: function (sprite) {

        if (this.shotsLeft === 0)
        {
            return;
        }

        var ball = this.balls.getFirstDead();

        if (ball)
        {
            ball.reset(sprite.x + 80, sprite.y);
        }
        else
        {
            ball = this.balls.create(sprite.x + 80, sprite.y, 'ball');
            ball.body.setCircle(28);
            ball.body.fixedRotation = true;
        }

        ball.foul = false;

        ball.body.applyImpulseLocal([ 0, 26 ], 0, 0);

        sprite.frameName = 'player' + sprite.name + 'up';

        var tween = this.add.tween(sprite).to( { y: "-32" }, 250, "Sine.easeInOut", true, 0, 0, true);
        tween.onComplete.add(this.jumpOver, this);

        this.shotsLeft--;
        this.shotsLeftText.text = "SHOTS: " + this.shotsLeft;

    },

    jumpOver: function (sprite) {

        sprite.frameName = 'player' + sprite.name + 'down';

    },

    update: function () {

        this.balls.forEachAlive(this.checkY, this);

        if (this.board.x >= 715 && this.board.body.velocity.x > 0)
        {
            this.board.body.velocity.x = -this.boardSpeed;
        }
        else if (this.board.x <= 85 && this.board.body.velocity.x < 0)
        {
            this.board.body.velocity.x = this.boardSpeed;
        }

    },

    checkY: function (ball) {

        if (ball.y > 550)
        {
            ball.kill();

            if (this.shotsLeft === 0)
            {
                this.gameOver();
            }
        }

    },

    preRender: function () {

        this.basket.x = this.board.x;
        this.basket.y = this.board.y+60;

    },

    gameOver: function () {

        this.state.start('Hoops.MainMenu');

   }

};

var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'game');

game.state.add('Hoops.Preloader', Hoops.Preloader);
game.state.add('Hoops.MainMenu', Hoops.MainMenu);
game.state.add('Hoops.Game', Hoops.Game);

game.state.start('Hoops.Preloader');

var timer;
var total = 0;

function create() {

    game.stage.backgroundColor = '#000';

    //  Create our Timer
    timer = game.time.create(false);

    //  Set a TimerEvent to occur after 2 seconds
    timer.loop(2000, updateCounter, this);

    //  Start the timer running - this is important!
    //  It won't start automatically, allowing you to hook it to button events and the like.
    timer.start();

}

function updateCounter() {

    total++;
    }
 this.timerText = this.add.bitmapText(14, 0, 'fat-and-tiny', 'SCORE: 0', 30);
        this.timerText.smoothed = false;
this.timerText.text = "TIME: " + this.timer;
<commit_msg>Create game.js<commit_after>var Hoops = {
    showDebug: false
};

Hoops.Preloader = function () {};

Hoops.Preloader.prototype = {

    init: function () {

        this.input.maxPointers = 10;

        this.scale.pageAlignHorizontally = true;

        this.physics.startSystem(Phaser.Physics.P2JS);

    },

    preload: function () {

        this.load.path = 'assets/';

        this.load.atlas('player');

        this.load.physics('basket');

        this.load.bitmapFont('fat-and-tiny');

        this.load.images([ 'logo', 'ball', 'basket', 'board' ]);

    },

    create: function () {

        this.state.start('Hoops.MainMenu');

    }

};

Hoops.MainMenu = function () {};

Hoops.MainMenu.prototype = {

    create: function () {

        this.stage.backgroundColor = 0x001133;

        var logo = this.add.image(this.world.centerX, 80, 'logo');
        logo.anchor.x = 0.5;

        var start = this.add.bitmapText(this.world.centerX, 460, 'fat-and-tiny', 'CLICK TO PLAY ;) ', 64);
        start.anchor.x = 0.5;
        start.smoothed = false;

        this.input.onDown.addOnce(this.start, this);

    },

    start: function () {

        this.state.start('Hoops.Game');

    }

};

Hoops.Game = function () {

    this.score = 0;
    this.scoreText = null;

    this.shotsLeft = 20;
    this.shotsLeftText = null;

    this.player1 = null;
    this.player2 = null;
    this.player3 = null;
    this.player4 = null;
    this.player5 = null;

    this.balls = null;

    this.board = null;
    this.basket = null;

    this.boardSpeed = 80;

    this.pauseKey = null;
    this.debugKey = null;

};

Hoops.Game.prototype = {

    init: function () {

        this.physics.p2.gravity.y = 300;
        this.physics.p2.restitution = 0.8;

        this.score = 0;
        this.shotsLeft = 20;

    },

    create: function () {

        this.stage.backgroundColor = 0xDC143C;

        this.board = this.add.sprite(700, 200, 'board');

        this.physics.p2.enable(this.board, Hoops.showDebug);

        this.board.body.static = true;
        this.board.body.clearShapes();
        this.board.body.loadPolygon('basket', 'basket');

        var circle = this.board.body.addCircle(12, 0, 90);
        circle.sensor = true;

        this.board.body.data.gravityScale = 0;
        this.board.body.velocity.x = this.boardSpeed;

        this.board.body.onBeginContact.add(this.checkBall, this);

        this.balls = this.add.physicsGroup(Phaser.Physics.P2JS);
        this.balls.enableBodyDebug = Hoops.showDebug;

        this.basket = this.add.sprite(100, 400, 'basket');
        this.basket.anchor.set(0.5);

        this.player1 = this.add.sprite(60, 430, 'player', 'player1down');
        this.player2 = this.add.sprite(190, 410, 'player', 'player2down');
        this.player3 = this.add.sprite(320, 390, 'player', 'player3down');
        this.player4 = this.add.sprite(450, 410, 'player', 'player4down');
        this.player5 = this.add.sprite(580, 430, 'player', 'player5down');

        for (var i = 1; i <= 5; i++)
        {
            this['player' + i].name = i;
            this['player' + i].inputEnabled = true;
            this['player' + i].events.onInputDown.add(this.shoot, this);
        }

        //  Score
        this.scoreText = this.add.bitmapText(16, 0, 'fat-and-tiny', 'SCORE: 0', 32);
        this.scoreText.smoothed = false;

        this.shotsLeftText = this.add.bitmapText(660, 0, 'fat-and-tiny', 'SHOTS: ' + this.shotsLeft, 32);
        this.shotsLeftText.smoothed = false;

        //  Press P to pause and resume the game
        this.pauseKey = this.input.keyboard.addKey(Phaser.Keyboard.P);
        this.pauseKey.onDown.add(this.togglePause, this);

        //  Press D to toggle the debug display
        this.debugKey = this.input.keyboard.addKey(Phaser.Keyboard.D);
        this.debugKey.onDown.add(this.toggleDebug, this);

    },

    togglePause: function () {

        this.game.paused = (this.game.paused) ? false : true;

    },

    toggleDebug: function () {

        Hoops.showDebug = (Hoops.showDebug) ? false : true;

        this.state.restart();

    },

    checkBall: function (body, bodyB, shapeA, shapeB, equation) {

        if (shapeA.type === 1 && shapeB.type === 1)
        {
            //  We've got 2 circles, work out which one is the sensor
            var ball = shapeA.body;

            if (shapeA.sensor)
            {
                ball = shapeB.body;
            }

            if (ball.velocity[1] > 0)
            {
                //  Ball is going UP through the net, so it's a foul
                ball.parent.sprite.foul = true;
            }
            else
            {
                if (!ball.parent.sprite.foul)
                {
                    this.score++;
                    this.scoreText.text = "SCORE: " + this.score;
                }
            }
        }

    },

    shoot: function (sprite) {

        if (this.shotsLeft === 0)
        {
            return;
        }

        var ball = this.balls.getFirstDead();

        if (ball)
        {
            ball.reset(sprite.x + 80, sprite.y);
        }
        else
        {
            ball = this.balls.create(sprite.x + 80, sprite.y, 'ball');
            ball.body.setCircle(28);
            ball.body.fixedRotation = true;
        }

        ball.foul = false;

        ball.body.applyImpulseLocal([ 0, 26 ], 0, 0);

        sprite.frameName = 'player' + sprite.name + 'up';

        var tween = this.add.tween(sprite).to( { y: "-32" }, 250, "Sine.easeInOut", true, 0, 0, true);
        tween.onComplete.add(this.jumpOver, this);

        this.shotsLeft--;
        this.shotsLeftText.text = "SHOTS: " + this.shotsLeft;

    },

    jumpOver: function (sprite) {

        sprite.frameName = 'player' + sprite.name + 'down';

    },

    update: function () {

        this.balls.forEachAlive(this.checkY, this);

        if (this.board.x >= 715 && this.board.body.velocity.x > 0)
        {
            this.board.body.velocity.x = -this.boardSpeed;
        }
        else if (this.board.x <= 85 && this.board.body.velocity.x < 0)
        {
            this.board.body.velocity.x = this.boardSpeed;
        }

    },

    checkY: function (ball) {

        if (ball.y > 550)
        {
            ball.kill();

            if (this.shotsLeft === 0)
            {
                this.gameOver();
            }
        }

    },

    preRender: function () {

        this.basket.x = this.board.x;
        this.basket.y = this.board.y+60;

    },

    gameOver: function () {

        this.state.start('Hoops.MainMenu');

   }

};

var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'game');

game.state.add('Hoops.Preloader', Hoops.Preloader);
game.state.add('Hoops.MainMenu', Hoops.MainMenu);
game.state.add('Hoops.Game', Hoops.Game);

game.state.start('Hoops.Preloader');

var timer;
var total = 0;

function create() {

    game.stage.backgroundColor = '#000';

    //  Create our Timer
    timer = game.time.create(false);

    //  Set a TimerEvent to occur after 2 seconds
    timer.loop(2000, updateCounter, this);

    //  Start the timer running - this is important!
    //  It won't start automatically, allowing you to hook it to button events and the like.
    timer.start();

}

function updateCounter() {

    total++;
    }
 this.timerText = this.add.bitmapText(14, 0, 'fat-and-tiny', 'SCORE: 0', 30);
        this.timerText.smoothed = false;
this.timerText.text = "TIME: " + this.timer;
<|endoftext|>


<commit_before>'use strict';

const mongoose = require('mongoose');
const logger = require('heroku-logger');

const Messages = require('./Message');
const facebook = require('../../lib/facebook');
const slack = require('../../lib/slack');
const twilio = require('../../lib/twilio');

const defaultTopic = 'random';

/**
 * Schema.
 */
const conversationSchema = new mongoose.Schema({
  platform: String,
  platformUserId: {
    type: String,
    index: true,
  },
  paused: Boolean,
  topic: String,
  campaignId: Number,
  signupStatus: String,
  lastOutboundMessage: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Message',
  },
  slackChannel: String,
  lastBroadcastId: String,
}, { timestamps: true });

/**
 * @param {Object} req - Express request
 * @return {Promise}
 */
conversationSchema.statics.createFromReq = function (req) {
  const data = {
    platformUserId: req.platformUserId,
    platform: req.platform,
    paused: false,
    topic: defaultTopic,
  };

  if (req.slackChannel) {
    data.slackChannel = req.slackChannel;
  }

  return this.create(data);
};

/**
 * @param {Object} req - Express request
 * @return {Promise}
 */
conversationSchema.statics.getFromReq = function (req) {
  const query = { platformUserId: req.platformUserId };
  logger.trace('Conversation.getFromReq', query);

  return this.findOne(query).populate('lastOutboundMessage');
};

/**
 * Update topic and check whether to toggle paused.
 * @return {boolean}
 */
conversationSchema.methods.setTopic = function (newTopic) {
  if (this.topic === newTopic) {
    return this.save();
  }

  const supportTopic = 'support';

  if (this.topic === supportTopic && newTopic !== supportTopic) {
    this.paused = false;
  }

  if (this.topic !== supportTopic && newTopic === supportTopic) {
    this.paused = true;
  }

  this.topic = newTopic;
  logger.trace('Conversation.setTopic', { newTopic });

  return this.save();
};

/**
 * Set topic to random to upause User.
 */
conversationSchema.methods.supportResolved = function () {
  return this.setTopic(defaultTopic);
};

/**
 * Returns save of User for updating given Campaign and its topic.
 * @param {Campaign} campaign
 * @return {Promise}
 */
conversationSchema.methods.setCampaignWithSignupStatus = function (campaign, signupStatus) {
  this.topic = campaign.topic;
  this.campaignId = campaign._id;
  this.signupStatus = signupStatus;
  logger.debug('setCampaignWithSignupStatus', { campaign: this.campaignId, signupStatus });

  return this.save();
};

/**
 * Post signup for current campaign and set it as the topic.
 * @param {Campaign} campaign
 * @param {string} source
 * @param {string} keyword
 */
conversationSchema.methods.setCampaign = function (campaign) {
  return this.setCampaignWithSignupStatus(campaign, 'doing');
};

/**
 * Prompt signup for current campaign.
 * @param {Campaign} campaign
 * @param {string} source
 * @param {string} keyword
 */
conversationSchema.methods.promptSignupForCampaign = function (campaign) {
  this.setCampaignWithSignupStatus(campaign, 'prompt');
};

/**
 * Prompt signup for current campaign and broadcast
 * @param {Campaign} campaign
 * @param {string} source
 * @param {string} keyword
 */
conversationSchema.methods.promptSignupForBroadcast = function (campaign, broadcastId) {
  this.lastBroadcastId = broadcastId;
  this.setCampaignWithSignupStatus(campaign, 'prompt');
};

/**
 * Decline signup for current campaign.
 * @param {Campaign} campaign
 * @param {string} source
 * @param {string} keyword
 */
conversationSchema.methods.declineSignup = function () {
  this.signupStatus = 'declined';
  return this.save();
};

/**
 * Gets data for a Conversation Message.
 * @param {string} text
 * @param {string} template
 * @return {object}
 */
conversationSchema.methods.getMessagePayload = function (text, template) {
  const data = {
    conversationId: this,
    campaignId: this.campaignId,
    topic: this.topic,
  };
  if (text) {
    data.text = text;
  }
  if (template) {
    data.template = template;
  }
  return data;
};

/**
 * Creates Message for a Conversation with given params.
 * @param {string} direction
 * @param {string} text
 * @param {string} template
 * @param {array} attachments
 * @return {Promise}
 */
conversationSchema.methods.createMessage = function (direction, text, template, attachments) {
  logger.debug('createMessage', { direction });

  const data = {
    text,
    direction,
    template,
    attachments,
  };
  Object.assign(data, this.getMessagePayload());

  // TODO: Handle platform dependent message properties here

  return Messages.create(data);
};

/**
 * Creates Message with given params and saves it to lastOutboundMessage.
 * @param {string} direction
 * @param {string} text
 * @param {string} template
 * @return {Promise}
 */
conversationSchema.methods.createLastOutboundMessage = function (direction, text, template) {
  return this.createMessage(direction, text, template)
    .then((message) => {
      this.lastOutboundMessage = message;

      return this.save();
    })
    .then(() => this.populate('lastOutboundMessage').execPopulate());
};

/**
 * @param {string} text
 * @param {string} template
 * @return {Promise}
 */
conversationSchema.methods.createAndPostOutboundReplyMessage = function (text, template) {
  return this.createLastOutboundMessage('outbound-reply', text, template)
    .then(() => this.postLastOutboundMessageToPlatform());
};

/**
 * @param {string} text
 * @param {string} template
 * @return {Promise}
 */
conversationSchema.methods.createAndPostOutboundSendMessage = function (text, template) {
  return this.createLastOutboundMessage('outbound-api-send', text, template)
    .then(() => this.postLastOutboundMessageToPlatform());
};

/**
 * @param {string} text
 * @param {string} template
 * @return {Promise}
 */
conversationSchema.methods.createOutboundImportMessage = function (text, template) {
  return this.createLastOutboundMessage('outbound-api-import', text, template);
};

/**
 * Posts the Last Outbound Message to the platform.
 */
conversationSchema.methods.postLastOutboundMessageToPlatform = function () {
  const loggerMessage = 'conversation.postLastOutboundMessageToPlatform';
  const messageText = this.lastOutboundMessage.text;
  // This could be blank for noReply templates.
  if (!messageText) {
    return;
  }
  logger.debug(loggerMessage);

  if (this.platform === 'slack') {
    slack.postMessage(this.slackChannel, messageText);
  }

  if (this.platform === 'sms') {
    twilio.postMessage(this.platformUserId, messageText)
      .then(res => logger.debug(loggerMessage, { status: res.status }))
      .catch(err => logger.error(loggerMessage, err));
  }

  if (this.platform === 'facebook') {
    facebook.postMessage(this.platformUserId, messageText);
  }
};

module.exports = mongoose.model('Conversation', conversationSchema);
<commit_msg>added loadInboundMessageAndUpdateMetadataByRequestId method to load an inbound request if this is a retry request<commit_after>'use strict';

const mongoose = require('mongoose');
const logger = require('heroku-logger');

const Messages = require('./Message');
const facebook = require('../../lib/facebook');
const slack = require('../../lib/slack');
const twilio = require('../../lib/twilio');

const defaultTopic = 'random';

/**
 * Schema.
 */
const conversationSchema = new mongoose.Schema({
  platform: String,
  platformUserId: {
    type: String,
    index: true,
  },
  paused: Boolean,
  topic: String,
  campaignId: Number,
  signupStatus: String,
  lastOutboundMessage: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Message',
  },
  slackChannel: String,
  lastBroadcastId: String,
}, { timestamps: true });

/**
 * @param {Object} req - Express request
 * @return {Promise}
 */
conversationSchema.statics.createFromReq = function (req) {
  const data = {
    platformUserId: req.platformUserId,
    platform: req.platform,
    paused: false,
    topic: defaultTopic,
  };

  if (req.slackChannel) {
    data.slackChannel = req.slackChannel;
  }

  return this.create(data);
};

/**
 * @param {Object} req - Express request
 * @return {Promise}
 */
conversationSchema.statics.getFromReq = function (req) {
  const query = { platformUserId: req.platformUserId };
  logger.trace('Conversation.getFromReq', query);

  return this.findOne(query).populate('lastOutboundMessage');
};

/**
 * Update topic and check whether to toggle paused.
 * @return {boolean}
 */
conversationSchema.methods.setTopic = function (newTopic) {
  if (this.topic === newTopic) {
    return this.save();
  }

  const supportTopic = 'support';

  if (this.topic === supportTopic && newTopic !== supportTopic) {
    this.paused = false;
  }

  if (this.topic !== supportTopic && newTopic === supportTopic) {
    this.paused = true;
  }

  this.topic = newTopic;
  logger.trace('Conversation.setTopic', { newTopic });

  return this.save();
};

/**
 * Set topic to random to upause User.
 */
conversationSchema.methods.supportResolved = function () {
  return this.setTopic(defaultTopic);
};

/**
 * Returns save of User for updating given Campaign and its topic.
 * @param {Campaign} campaign
 * @return {Promise}
 */
conversationSchema.methods.setCampaignWithSignupStatus = function (campaign, signupStatus) {
  this.topic = campaign.topic;
  this.campaignId = campaign._id;
  this.signupStatus = signupStatus;
  logger.debug('setCampaignWithSignupStatus', { campaign: this.campaignId, signupStatus });

  return this.save();
};

/**
 * Post signup for current campaign and set it as the topic.
 * @param {Campaign} campaign
 * @param {string} source
 * @param {string} keyword
 */
conversationSchema.methods.setCampaign = function (campaign) {
  return this.setCampaignWithSignupStatus(campaign, 'doing');
};

/**
 * Prompt signup for current campaign.
 * @param {Campaign} campaign
 * @param {string} source
 * @param {string} keyword
 */
conversationSchema.methods.promptSignupForCampaign = function (campaign) {
  this.setCampaignWithSignupStatus(campaign, 'prompt');
};

/**
 * Prompt signup for current campaign and broadcast
 * @param {Campaign} campaign
 * @param {string} source
 * @param {string} keyword
 */
conversationSchema.methods.promptSignupForBroadcast = function (campaign, broadcastId) {
  this.lastBroadcastId = broadcastId;
  this.setCampaignWithSignupStatus(campaign, 'prompt');
};

/**
 * Decline signup for current campaign.
 * @param {Campaign} campaign
 * @param {string} source
 * @param {string} keyword
 */
conversationSchema.methods.declineSignup = function () {
  this.signupStatus = 'declined';
  return this.save();
};

/**
 * Loads the inbound message that matches this conversationId and
 * the metadata.requestId and updates its metadata with the new one.
 * @param {number} requestId
 * @param {object} metadata
 * @return {object}
 */
conversationSchema.methods.loadInboundMessageAndUpdateMetadataByRequestId = function (requestId,
  metadata = {}) {
  const query = {
    conversationId: this._id,
    'metadata.requestId': requestId,
    direction: 'inbound',
  };
  const update = { metadata };
  const options = { new: true };
  return Messages.findOneAndUpdate(query, update, options)
    .then(message => message.populate('conversationId').execPopulate())
    .then(() => {
      this.populate('lastOutboundMessage').execPopulate();
    });
};

/**
 * Gets data for a Conversation Message.
 * @param {string} text
 * @param {string} template
 * @return {object}
 */
conversationSchema.methods.getDefaultMessagePayload = function (text, template) {
  const data = {
    conversationId: this,
    campaignId: this.campaignId,
    topic: this.topic,
  };
  if (text) {
    data.text = text;
  }
  if (template) {
    data.template = template;
  }
  return data;
};

/**
 * Gets data from a req object for a Conversation Message.
 * @param {string} text
 * @param {string} template
 * @return {object}
 */
conversationSchema.methods.getMessagePayloadFromReq = function (req = {}) {
  // TODO: Handle platform dependent message properties here
  const data = {
    metadata: req.metadata || {},
    attachments: req.attachments || [],
  };
  return data;
};

/**
 * Creates Message for a Conversation with given params.
 * @param {string} direction
 * @param {string} text
 * @param {string} template
 * @param {array} attachments
 * @return {Promise}
 */
conversationSchema.methods.createMessage = function (direction, text, template, req) {
  logger.debug('createMessage', { direction });

  const data = {
    text,
    direction,
    template,
  };

  // Merge default payload and payload from req
  Object.assign(data, this.getDefaultMessagePayload(), this.getMessagePayloadFromReq(req));

  return Messages.create(data);
};

/**
 * Creates Message with given params and saves it to lastOutboundMessage.
 * @param {string} direction
 * @param {string} text
 * @param {string} template
 * @return {Promise}
 */
conversationSchema.methods.createLastOutboundMessage = function (direction, text, template, req) {
  return this.createMessage(direction, text, template, req)
    .then((message) => {
      this.lastOutboundMessage = message;

      return this.save();
    })
    .then(() => this.populate('lastOutboundMessage').execPopulate());
};

/**
 * @param {string} text
 * @param {string} template
 * @return {Promise}
 */
conversationSchema.methods.createAndPostOutboundReplyMessage = function (text, template, req) {
  return this.createLastOutboundMessage('outbound-reply', text, template, req)
    .then(() => this.postLastOutboundMessageToPlatform());
};

/**
 * @param {string} text
 * @param {string} template
 * @return {Promise}
 */
conversationSchema.methods.createAndPostOutboundSendMessage = function (text, template, req) {
  return this.createLastOutboundMessage('outbound-api-send', text, template, req)
    .then(() => this.postLastOutboundMessageToPlatform());
};

/**
 * @param {string} text
 * @param {string} template
 * @return {Promise}
 */
conversationSchema.methods.createOutboundImportMessage = function (text, template, req) {
  return this.createLastOutboundMessage('outbound-api-import', text, template, req);
};

/**
 * Posts the Last Outbound Message to the platform.
 */
conversationSchema.methods.postLastOutboundMessageToPlatform = function () {
  const loggerMessage = 'conversation.postLastOutboundMessageToPlatform';
  const messageText = this.lastOutboundMessage.text;
  // This could be blank for noReply templates.
  if (!messageText) {
    return;
  }
  logger.debug(loggerMessage);

  if (this.platform === 'slack') {
    slack.postMessage(this.slackChannel, messageText);
  }

  if (this.platform === 'sms') {
    twilio.postMessage(this.platformUserId, messageText)
      .then(res => logger.debug(loggerMessage, { status: res.status }))
      .catch(err => logger.error(loggerMessage, err));
  }

  if (this.platform === 'facebook') {
    facebook.postMessage(this.platformUserId, messageText);
  }
};

module.exports = mongoose.model('Conversation', conversationSchema);
<|endoftext|>


<commit_before>'use babel';
'use strict';

import { Command, CommandFormatError } from 'discord-graf';
import { oneLine } from 'common-tags';
import Character from '../../database/character';

export default class AddCharacterCommand extends Command {
	constructor(bot) {
		super(bot);
		this.name = 'addcharacter';
		this.aliases = ['addchar'];
		this.group = 'characters';
		this.groupName = 'add';
		this.description = 'Adds a character to the database, or updates the existing one.';
		this.usage = 'addcharacter <name> <info>';
		this.details = oneLine`
			The character name can be a maximum of 60 characters long, and must be surrounded by quotes if it contains spaces.
			The information doesn\'t have to be a single line.
			Only the owner of the character and administrators/moderators may update it.
		`;
		this.examples = ['addcharacter Bob Just your average guy.', 'addcharacter "Billy McBillface" A really cool guy who enjoys his chicken tendies.'];
		this.serverOnly = true;
		this.argsType = 'multiple';
		this.argsCount = 2;
	}

	async run(message, args) {
		const name = args[0], info = args[1];
		if(!name || !info) throw new CommandFormatError(this, message.server);
		if(this.bot.util.patterns.anyUserMentions.test(name)
			|| this.bot.util.patterns.anyUserMentions.test(info)) return 'Please do not use mentions in your character name or information.';

		// Apply some restrictions
		if(name.length > 60) return 'A character\'s name may not be longer than 60 characters.';
		if(name.includes('\n')) return 'A character\'s name may not have multiple lines.';

		// Add or update the character
		const result = await Character.save(new Character(message.server, message.author, name, info));
		if(result) {
			return `${result.new ? 'Added' : 'Updated'} character "${name}".`;
		} else {
			return `Unable to update character "${name}". You are not the owner.`;
		}
	}
}
<commit_msg>Disabled single quotes arg parsing in addchar<commit_after>'use babel';
'use strict';

import { Command, CommandFormatError } from 'discord-graf';
import { oneLine } from 'common-tags';
import Character from '../../database/character';

export default class AddCharacterCommand extends Command {
	constructor(bot) {
		super(bot);
		this.name = 'addcharacter';
		this.aliases = ['addchar'];
		this.group = 'characters';
		this.groupName = 'add';
		this.description = 'Adds a character to the database, or updates the existing one.';
		this.usage = 'addcharacter <name> <info>';
		this.details = oneLine`
			The character name can be a maximum of 60 characters long, and must be surrounded by quotes if it contains spaces.
			The information doesn\'t have to be a single line.
			Only the owner of the character and administrators/moderators may update it.
		`;
		this.examples = ['addcharacter Bob Just your average guy.', 'addcharacter "Billy McBillface" A really cool guy who enjoys his chicken tendies.'];
		this.serverOnly = true;
		this.argsType = 'multiple';
		this.argsCount = 2;
		this.argsSingleQuotes = false;
	}

	async run(message, args) {
		const name = args[0], info = args[1];
		if(!name || !info) throw new CommandFormatError(this, message.server);
		if(this.bot.util.patterns.anyUserMentions.test(name)
			|| this.bot.util.patterns.anyUserMentions.test(info)) return 'Please do not use mentions in your character name or information.';

		// Apply some restrictions
		if(name.length > 60) return 'A character\'s name may not be longer than 60 characters.';
		if(name.includes('\n')) return 'A character\'s name may not have multiple lines.';

		// Add or update the character
		const result = await Character.save(new Character(message.server, message.author, name, info));
		if(result) {
			return `${result.new ? 'Added' : 'Updated'} character "${name}".`;
		} else {
			return `Unable to update character "${name}". You are not the owner.`;
		}
	}
}
<|endoftext|>


<commit_before>
var xy = {};

xy.Grid = function(parent, size) {
	this.grid = document.createElement("div");
	this.grid.className = "grid grid" + size;

	for (var r = 0; r < size; r++) {
		var row = document.createElement("div");
		row.className = "grid-row";

		for (var t = 0; t < size; t++) {
			var tile = document.createElement("div");
			tile.className = "tile";

			row.appendChild(tile);
		}

		this.grid.appendChild(row);
	}

	parent.appendChild(this.grid);
}

xy.Game = function(parent) {
	this.parent = parent;
	this.grid = new xy.Grid(parent, 4);
}<commit_msg>add tile change on click<commit_after>
var xy = {};

xy.Grid = function(parent, size) {
	this.grid = document.createElement("div");
	this.grid.className = "grid grid" + size;

	for (var r = 0; r < size; r++) {
		var row = document.createElement("div");
		row.className = "grid-row";

		for (var c = 0; c < size; c++) {
			var tile = document.createElement("div");
			tile.className = "tile";

			tile.addEventListener("click", (function(grid, r, c) {
				return function(e) {
					grid.tileClicked(e, r, c);
				};
			})(this, r, c));

			row.appendChild(tile);
		}

		this.grid.appendChild(row);
	}

	parent.appendChild(this.grid);
}

xy.Grid.prototype.tileClicked = function(event, r, c) {
	// console.log("click @ {r: " + r + ", c: " + c + "}");

	var tile = event.target;

	if (tile.classList.contains("x")) {
		tile.className = "tile y";
	} else if (tile.classList.contains("y")) {
		tile.className = "tile";
	} else {
		tile.className = "tile x";
	}
}

xy.Game = function(parent) {
	this.parent = parent;
	this.grid = new xy.Grid(parent, 4);
}<|endoftext|>


<commit_before>const r = require("rethinkdb");
const lang = [
	"en",
	"pi"
];

module.exports = function (message) {
	//Split message into keywords
	let input = message.content.replace(/\n/g, "").split(" ");

	console.log(`Setting language of ${message.member.tag} to ${input[2]}`);

	//Check if the input is a valid language
	if(lang[input[2]]) {
		console.log(`Successfully found language`);

		r.table("users").insert(
			{"id": message.member.id, "lang": input[2]},
			conflict = "replace"
		).run(message.guild.rethonk);
	}
}
<commit_msg>remove rethonk for testing<commit_after>const r = require("rethinkdb");
const lang = [
	"en",
	"pi"
];

module.exports = function (message) {
	//Split message into keywords
	let input = message.content.replace(/\n/g, "").split(" ");

	console.log(`Setting language of ${message.member.tag} to ${input[2]}`);

	//Check if the input is a valid language
	if(lang[input[2]]) {
		console.log(`Successfully found language`);
	}
}

//r.table("users").insert(
//	{"id": message.member.id, "lang": input[2]},
//	conflict = "replace"
//).run(message.guild.rethonk);
<|endoftext|>


<commit_before>const Util = require('../../util');
const { Group, DomUtil } = require('@ali/g');

const CONTAINER_CLASS = 'g2-legend';
const TITLE_CLASS = 'g2-tooltip-title';
const LIST_CLASS = 'g2-tooltip-list';

function find(dom, cls) {
  return dom.getElementsByClassName(cls)[0];
}

function isInPlot(range, point) {
  const { tl, br } = range;
  const { x, y } = point;
  const result = {};
  result.inPlot = (x >= tl.x && x <= br.x && y >= tl.y && y <= br.y);
  result.inHorizontal = (x >= tl.x && x <= br.x);
  result.inVertical = (y >= tl.y && y <= br.y);

  return result;
}

class Tooltip extends Group {
  getDefaultCfg() {
    return {
      zIndex: 10,
      x: 0, // @type {Number} x 右下角坐标
      y: 0, // @type {Number} y 右下角坐标
      items: null, // @type {Array} tooltip 子项
      showTitle: true, // 是否展示 title
      titleContent: undefined, // @type {String} 默认标题文本
      crosshairs: null, // @type {Boolean} 是否贯穿整个坐标轴
      crossLineShapeX: null, // @type {Shape} X标记线图形
      crossLineShapeY: null, // @type {Shape} Y标记线图形
      plotRange: null, // @type {Object} 视图范围
      offset: 10, // @type {Number} x轴上，移动到位置的偏移量
      animate: true, // @type {Boolean} 是否开启动画
      duration: 50, // @type {Number} 移动的动画时间
      container: null, // @type {Boolean} 是否自定义HTML
      timeStamp: 0, // @type {Nmuber} 时间戳
      // @type {String} 使用html时的外层模板
      containerTpl: '<div class="' + CONTAINER_CLASS + '" style="position:absolute;visibility:hidden;border-style:solid;white-space:nowrap;z-index:9999999;transition:left 0.4s cubic-bezier(0.23, 1, 0.32, 1), top 0.4s cubic-bezier(0.23, 1, 0.32, 1);background-color:rgba(50, 50, 50, 0.7);border-width:0px;border-color:rgb(51, 51, 51);border-radius:4px;color:rgb(255, 255, 255);font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;font-family:sans-serif;line-height:21px;padding:5px 10px;">'
       + '

'
       + '

',
      // @type {String} 使用html时，单个选项的模板
      itemTpl: '
${ name }: ${ value }
',
      inPlot: true
    };
  }

  _setTooltipWrapper() {
    const self = this;
    const containerTpl = self.get('containerTpl');
    const outterNode = self.get('canvas').get('el').parentNode;
    let container;
    if (/^\#/.test(containerTpl)) { // 如果传入 dom 节点的 id
      const id = containerTpl.replace('#', '');
      container = document.getElementById(id);
    } else {
      container = DomUtil.createDom(containerTpl);
    }
    self.set('container', container);
    outterNode.appendChild(container);
    outterNode.style.position = 'relative';
  }

  _beforeRenderUI() {
    const crosshairs = this.get('crosshairs');
    if (crosshairs && crosshairs.type === 'rect') {
      Util.defaultsDeep(this.get('crosshairs'), {
        style: {
          fill: '#CCD7EB',
          opacity: 0.4,
          lineWidth: 0
        }
      });
    } else {
      Util.defaultsDeep(this.get('crosshairs'), {
        style: {
          stroke: '#666',
          lineWidth: 1
        }
      });
    }

    const crosshairsGroup = this.addGroup({
      zIndex: 0
    });

    this.set('crosshairsGroup', crosshairsGroup);
    this._setTooltipWrapper();
  }

  _renderUI() {
    if (this.get('items')) {
      this._renderTooltip();
    }
    this._renderCrosshairs();
  }

  _clearDom() {
    const container = this.get('container');
    const titleDom = find(container, TITLE_CLASS);
    const listDom = find(container, LIST_CLASS);
    if (titleDom) {
      titleDom.innerHTML = '';
    }
    if (listDom) {
      listDom.innerHTML = '';
    }
  }

  _addItem(item, index) {
    const container = this.get('container');
    const listDom = find(container, LIST_CLASS);
    const itemTpl = this.get('itemTpl'); // TODO: 有可能是个回调函数

    const itemTplCompiler = Util.template(itemTpl);
    const itemDiv = itemTplCompiler({
      index,
      color: item.color,
      value: item.value,
      name: item.name
    });

    const itemDOM = DomUtil.createDom(itemDiv);
    listDom.appendChild(itemDOM);
  }

  _renderTooltip() {
    const self = this;
    const showTitle = self.get('showTitle');
    const titleContent = self.get('titleContent');
    const container = self.get('container');
    const titleDom = find(container, TITLE_CLASS);
    const listDom = find(container, LIST_CLASS);
    const items = self.get('items');
    self._clearDom();

    if (titleDom && showTitle) {
      titleDom.innerHTML = titleContent;
    }

    if (listDom) {
      Util.each(items, (item, index) => {
        self._addItem(item, index);
      });
    }
  }

  _clearCrosshairsGroup() {
    const crosshairsGroup = this.get('crosshairsGroup');
    this.set('crossLineShapeX', null);
    this.set('crossLineShapeY', null);
    crosshairsGroup.clear();
  }

  _renderCrosshairs() {
    const crosshairs = this.get('crosshairs');
    const canvas = this.get('canvas');
    const plotRange = this.get('plotRange');
    if (crosshairs) {
      this._clearCrosshairsGroup();
      switch (crosshairs.type) {
        case 'x':
          this._renderHorizontalLine(canvas, plotRange);
          break;
        case 'y':
          this._renderVerticalLine(canvas, plotRange);
          break;
        case 'cross':
          this._renderHorizontalLine(canvas, plotRange);
          this._renderVerticalLine(canvas, plotRange);
          break;
        case 'rect':
          this._renderBackground(canvas, plotRange);
          break;
        default:
          this._renderVerticalLine(canvas, plotRange);
      }
    }
  }

  _addCrossLineShape(attrs, type) {
    const crosshairsGroup = this.get('crosshairsGroup');
    const shape = crosshairsGroup.addShape('line', {
      attrs
    });
    this.set('crossLineShape' + type, shape);
    return shape;
  }

  _renderVerticalLine(canvas, plotRange) {
    const { style } = this.get('crosshairs');
    const attrs = Util.mix({
      x1: 0,
      y1: plotRange ? plotRange.bl.y : canvas.get('height'),
      x2: 0,
      y2: plotRange ? plotRange.tl.y : 0
    }, style);

    this._addCrossLineShape(attrs, 'Y');
  }

  _renderHorizontalLine(canvas, plotRange) {
    const { style } = this.get('crosshairs');
    const attrs = Util.mix({
      x1: plotRange ? plotRange.bl.x : canvas.get('width'),
      y1: 0,
      x2: plotRange ? plotRange.br.x : 0,
      y2: 0
    }, style);

    this._addCrossLineShape(attrs, 'X');
  }

  _renderBackground(canvas, plotRange) {
    const { style } = this.get('crosshairs');
    const attrs = Util.mix({
      x: plotRange ? plotRange.tl.x : 0,
      y: plotRange ? plotRange.tl.y : canvas.get('height'),
      width: plotRange ? plotRange.br.x - plotRange.bl.x : canvas.get('width'),
      height: plotRange ? Math.abs(plotRange.tl.y - plotRange.bl.y) : canvas.get('height')
    }, style);

    const shape = this.addShape('rect', {
      attrs
    });
    shape.hide();
    this.set('crosshairsRectShape', shape);
    return shape;
  }

  _isContentChange(title, items) {
    const titleContent = this.get('titleContent');
    const lastItems = this.get('items');
    let isChanged = !(title === titleContent && lastItems.length === items.length);
    if (!isChanged) {
      Util.each(items, (item, index) => {
        const preItem = lastItems[index];
        isChanged = (item.value !== preItem.value) || (item.color !== preItem.color) || (item.name !== preItem.name) || (item.title !== preItem.title);
        if (isChanged) {
          return false;
        }
      });
    }

    return isChanged;
  }

  setContent(title, items) {
    const isChange = this._isContentChange(title, items);
    if (isChange) {
      const timeStamp = +new Date();
      this.set('items', items);
      this.set('titleContent', title);
      this.set('timeStamp', timeStamp);
      this._renderTooltip();
    }
    return this;
  }

  setMarkers(markerItems, markerCfg) {
    const self = this;
    let markerGroup = self.get('markerGroup');
    if (!markerGroup) {
      markerGroup = self.addGroup({
        zIndex: 1
      });
      self.set('markerGroup', markerGroup);
    } else {
      markerGroup.clear();
    }

    Util.each(markerItems, item => {
      markerGroup.addShape('marker', {
        attrs: Util.mix({}, markerCfg, {
          stroke: item.color,
          x: item.x,
          y: item.y
        })
      });
    });
  }

  clearMarkers() {
    const markerGroup = this.get('markerGroup');
    markerGroup && markerGroup.clear();
  }

  setPosition(x, y, isFixed) {
    const container = this.get('container');
    let offset = this.get('offset');
    const crossLineShapeX = this.get('crossLineShapeX');
    const crossLineShapeY = this.get('crossLineShapeY');
    const crosshairsRectShape = this.get('crosshairsRectShape');
    // const animate = this.get('animate');
    let after = true;
    const endx = x;
    const endy = y;
    const containerWidth = DomUtil.getWidth(container);
    const containerHeight = DomUtil.getHeight(container);

    if (isFixed) {
      x = x - containerWidth / 2;
      y = y - containerHeight - offset;
    } else {
      const width = containerWidth + 2 * offset;
      x = x - width;
      y = y - containerHeight - 2 * offset;
    }

    if (this.get('inPlot')) { // 限定必须展示在图表绘图区域内
      const plotRange = this.get('plotRange');
      const point = {
        x,
        y
      };
      const inPlot = isInPlot(plotRange, point);

      if (!inPlot.inPlot) {
        if (!inPlot.inHorizontal) {
          if ((plotRange.tr.x - plotRange.tl.x) >= 2 * containerWidth) {
            x = Math.max(plotRange.tl.x, endx) + offset;
            after = false;
          } else {
            x = plotRange.tl.x;
            y -= offset;
          }
        }

        if (!inPlot.inVertical) {
          y = plotRange.tl.y;
        }
      }
    }

    if (this.get('x') !== x || this.get('y') !== y) {
      if (crossLineShapeY) { // 第一次进入时，画布需要单独绘制，所以需要先设定corss的位置
        if (after) {
          crossLineShapeY.move(endx, 0);
        } else {
          crossLineShapeY.move((x - offset), 0);
        }
      }
      if (crossLineShapeX) {
        crossLineShapeX.move(0, endy);
      }

      if (crosshairsRectShape) {
        const isTransposed = this.get('isTransposed');
        const items = isTransposed ? this.get('items').reverse() : this.get('items');
        const firstItem = items[0];
        offset = (firstItem.size / 2 + firstItem.size / 4) || 10;
        const dim = isTransposed ? 'y' : 'x';
        const attr = isTransposed ? 'height' : 'width';

        crosshairsRectShape.attr(dim, firstItem.point[dim] - offset);

        if (items.length === 1) {
          crosshairsRectShape.attr(attr, firstItem.size + firstItem.size / 2);
        } else {
          const lastItem = items[items.length - 1];
          crosshairsRectShape.attr(attr, lastItem.point[dim] - firstItem.point[dim] + 2 * offset);
        }
      }

      container.style.left = x + 'px';
      container.style.top = y + 'px';
    }
  }

  show() {
    const crossLineShapeX = this.get('crossLineShapeX');
    const crossLineShapeY = this.get('crossLineShapeY');
    const crosshairsRectShape = this.get('crosshairsRectShape');
    const markerGroup = this.get('markerGroup');
    const container = this.get('container');
    const hideHandler = this.get('hideHandler');
    const canvas = this.get('canvas');
    if (hideHandler) {
      clearTimeout(hideHandler);
    }
    crossLineShapeX && crossLineShapeX.show();
    crossLineShapeY && crossLineShapeY.show();
    crosshairsRectShape && crosshairsRectShape.show();
    markerGroup && markerGroup.show();
    super.show();
    container.style.visibility = 'visible';
    this.sort();
    canvas.draw();
  }

  hide() {
    const self = this;
    const container = self.get('container');
    const crossLineShapeX = self.get('crossLineShapeX');
    const crossLineShapeY = self.get('crossLineShapeY');
    const crosshairsRectShape = this.get('crosshairsRectShape');
    const markerGroup = self.get('markerGroup');
    const canvas = self.get('canvas');
    const hideHandler = setTimeout(function() {
      container.style.visibility = 'hidden';
      self.set('hideHandler', null);
      if (!self.get('destroyed')) {
        Tooltip.superclass.hide.call(self);
        canvas.draw();
      }
    }, self.get('duration'));
    self.set('hideHandler', hideHandler);
    crossLineShapeX && crossLineShapeX.hide();
    crossLineShapeY && crossLineShapeY.hide();
    crosshairsRectShape && crosshairsRectShape.hide();
    markerGroup && markerGroup.hide();
  }

  remove() {
    const self = this;
    const crossLineShapeX = self.get('crossLineShapeX');
    const crossLineShapeY = self.get('crossLineShapeY');
    const markerGroup = self.get('markerGroup');
    const crosshairsRectShape = self.get('crosshairsRectShape');
    const container = self.get('container');
    const containerTpl = self.get('containerTpl');

    crossLineShapeX && crossLineShapeX.remove();
    crossLineShapeY && crossLineShapeY.remove();
    markerGroup && markerGroup.remove();
    crosshairsRectShape && crosshairsRectShape.remove();
    super.remove();

    if (container && !(/^\#/.test(containerTpl))) {
      container.parentNode.removeChild(container);
    }
  }
}

module.exports = Tooltip;
<commit_msg>tooltip 背景框支持宽度设置；添加 tooltip 不跟随鼠标移动功能。<commit_after>const Util = require('../../util');
const { Group, DomUtil } = require('@ali/g');

const CONTAINER_CLASS = 'g2-tooltip';
const TITLE_CLASS = 'g2-tooltip-title';
const LIST_CLASS = 'g2-tooltip-list';

function find(dom, cls) {
  return dom.getElementsByClassName(cls)[0];
}

function isInPlot(range, point) {
  const { tl, br } = range;
  const { x, y } = point;
  const result = {};
  result.inPlot = (x >= tl.x && x <= br.x && y >= tl.y && y <= br.y);
  result.inHorizontal = (x >= tl.x && x <= br.x);
  result.inVertical = (y >= tl.y && y <= br.y);

  return result;
}

class Tooltip extends Group {
  getDefaultCfg() {
    return {
      zIndex: 10,
      /**
       * 右下角坐标
       * @type {Number}
       */
      x: 0,
      /**
       * y 右下角坐标
       * @type {Number}
       */
      y: 0,
      /**
       * tooltip 记录项
       * @type {Array}
       */
      items: null,
      /**
       * 是否展示 title
       * @type {Boolean}
       */
      showTitle: true,
      /**
       * tooltip 辅助线配置
       * @type {Object}
       */
      crosshairs: null,
      /**
       * 视图范围
       * @type {Object}
       */
      plotRange: null,
      /**
       * x轴上，移动到位置的偏移量
       * @type {Number}
       */
      offset: 10,
      /**
       * 是否开启动画
       * @type {Boolean}
       */
      animate: true,
      /**
       * 移动的动画时间
       * @type {Number}
       */
      duration: 50,
      /**
       * 时间戳
       * @type {Number}
       */
      timeStamp: 0,
      /**
       * tooltip 容器模板
       * @type {String}
       */
      containerTpl: '<div class="' + CONTAINER_CLASS + '" style="position:absolute;visibility:hidden;border-style:solid;white-space:nowrap;z-index:9999999;transition:left 0.4s cubic-bezier(0.23, 1, 0.32, 1), top 0.4s cubic-bezier(0.23, 1, 0.32, 1);background-color:rgba(50, 50, 50, 0.7);border-width:0px;border-color:rgb(51, 51, 51);border-radius:4px;color:rgb(255, 255, 255);font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;font-family:sans-serif;line-height:21px;padding:5px 10px;">'
       + '

'
       + '

',
      /**
       * tooltip 列表项模板
       * @type {String}
       */
      itemTpl: '
${ name }: ${ value }
',
      /**
       * 将 tooltip 展示在指定区域内
       * @type {Boolean}
       */
      inPlot: true,
      /**
       * tooltip 内容跟随鼠标移动
       * @type {Boolean}
       */
      follow: true
    };
  }

  _setTooltipWrapper() {
    const self = this;
    const containerTpl = self.get('containerTpl');
    const outterNode = self.get('canvas').get('el').parentNode;
    let container;
    if (/^\#/.test(containerTpl)) { // 如果传入 dom 节点的 id
      const id = containerTpl.replace('#', '');
      container = document.getElementById(id);
    } else {
      container = DomUtil.createDom(containerTpl);
    }
    self.set('container', container);
    outterNode.appendChild(container);
    outterNode.style.position = 'relative';
  }

  _beforeRenderUI() {
    const crosshairs = this.get('crosshairs');
    if (crosshairs && crosshairs.type === 'rect') {
      Util.defaultsDeep(this.get('crosshairs'), {
        style: {
          fill: '#CCD7EB',
          opacity: 0.4,
          lineWidth: 0
        }
      });
    } else {
      Util.defaultsDeep(this.get('crosshairs'), {
        style: {
          stroke: '#666',
          lineWidth: 1
        }
      });
    }

    const crosshairsGroup = this.addGroup({
      zIndex: 0
    });

    this.set('crosshairsGroup', crosshairsGroup);
    this._setTooltipWrapper();
  }

  _renderUI() {
    if (this.get('items')) {
      this._renderTooltip();
    }
    this._renderCrosshairs();
  }

  _clearDom() {
    const container = this.get('container');
    const titleDom = find(container, TITLE_CLASS);
    const listDom = find(container, LIST_CLASS);
    if (titleDom) {
      titleDom.innerHTML = '';
    }
    if (listDom) {
      listDom.innerHTML = '';
    }
  }

  _addItem(item, index) {
    const container = this.get('container');
    const listDom = find(container, LIST_CLASS);
    const itemTpl = this.get('itemTpl'); // TODO: 有可能是个回调函数

    const itemTplCompiler = Util.template(itemTpl);
    const itemDiv = itemTplCompiler({
      index,
      color: item.color,
      value: item.value,
      name: item.name
    });

    const itemDOM = DomUtil.createDom(itemDiv);
    listDom.appendChild(itemDOM);
  }

  _renderTooltip() {
    const self = this;
    const showTitle = self.get('showTitle');
    const titleContent = self.get('titleContent');
    const container = self.get('container');
    const titleDom = find(container, TITLE_CLASS);
    const listDom = find(container, LIST_CLASS);
    const items = self.get('items');
    self._clearDom();

    if (titleDom && showTitle) {
      titleDom.innerHTML = titleContent;
    }

    if (listDom) {
      Util.each(items, (item, index) => {
        self._addItem(item, index);
      });
    }
  }

  _clearCrosshairsGroup() {
    const crosshairsGroup = this.get('crosshairsGroup');
    this.set('crossLineShapeX', null);
    this.set('crossLineShapeY', null);
    crosshairsGroup.clear();
  }

  _renderCrosshairs() {
    const crosshairs = this.get('crosshairs');
    const canvas = this.get('canvas');
    const plotRange = this.get('plotRange');
    if (crosshairs) {
      this._clearCrosshairsGroup();
      switch (crosshairs.type) {
        case 'x':
          this._renderHorizontalLine(canvas, plotRange);
          break;
        case 'y':
          this._renderVerticalLine(canvas, plotRange);
          break;
        case 'cross':
          this._renderHorizontalLine(canvas, plotRange);
          this._renderVerticalLine(canvas, plotRange);
          break;
        case 'rect':
          this._renderBackground(canvas, plotRange);
          break;
        default:
          this._renderVerticalLine(canvas, plotRange);
      }
    }
  }

  _addCrossLineShape(attrs, type) {
    const crosshairsGroup = this.get('crosshairsGroup');
    const shape = crosshairsGroup.addShape('line', {
      attrs
    });
    this.set('crossLineShape' + type, shape);
    return shape;
  }

  _renderVerticalLine(canvas, plotRange) {
    const { style } = this.get('crosshairs');
    const attrs = Util.mix({
      x1: 0,
      y1: plotRange ? plotRange.bl.y : canvas.get('height'),
      x2: 0,
      y2: plotRange ? plotRange.tl.y : 0
    }, style);

    this._addCrossLineShape(attrs, 'Y');
  }

  _renderHorizontalLine(canvas, plotRange) {
    const { style } = this.get('crosshairs');
    const attrs = Util.mix({
      x1: plotRange ? plotRange.bl.x : canvas.get('width'),
      y1: 0,
      x2: plotRange ? plotRange.br.x : 0,
      y2: 0
    }, style);

    this._addCrossLineShape(attrs, 'X');
  }

  _renderBackground(canvas, plotRange) {
    const { style } = this.get('crosshairs');
    const attrs = Util.mix({
      x: plotRange ? plotRange.tl.x : 0,
      y: plotRange ? plotRange.tl.y : canvas.get('height'),
      width: plotRange ? plotRange.br.x - plotRange.bl.x : canvas.get('width'),
      height: plotRange ? Math.abs(plotRange.tl.y - plotRange.bl.y) : canvas.get('height')
    }, style);

    const shape = this.addShape('rect', {
      attrs
    });
    shape.hide();
    this.set('crosshairsRectShape', shape);
    return shape;
  }

  _isContentChange(title, items) {
    const titleContent = this.get('titleContent');
    const lastItems = this.get('items');
    let isChanged = !(title === titleContent && lastItems.length === items.length);
    if (!isChanged) {
      Util.each(items, (item, index) => {
        const preItem = lastItems[index];
        isChanged = (item.value !== preItem.value) || (item.color !== preItem.color) || (item.name !== preItem.name) || (item.title !== preItem.title);
        if (isChanged) {
          return false;
        }
      });
    }

    return isChanged;
  }

  setContent(title, items) {
    const isChange = this._isContentChange(title, items);
    if (isChange) {
      const timeStamp = +new Date();
      this.set('items', items);
      this.set('titleContent', title);
      this.set('timeStamp', timeStamp);
      this._renderTooltip();
    }
    return this;
  }

  setMarkers(markerItems, markerCfg) {
    const self = this;
    let markerGroup = self.get('markerGroup');
    if (!markerGroup) {
      markerGroup = self.addGroup({
        zIndex: 1
      });
      self.set('markerGroup', markerGroup);
    } else {
      markerGroup.clear();
    }

    Util.each(markerItems, item => {
      markerGroup.addShape('marker', {
        attrs: Util.mix({}, markerCfg, {
          stroke: item.color,
          x: item.x,
          y: item.y
        })
      });
    });
  }

  clearMarkers() {
    const markerGroup = this.get('markerGroup');
    markerGroup && markerGroup.clear();
  }

  setPosition(x, y, isFixed) {
    const container = this.get('container');
    const crossLineShapeX = this.get('crossLineShapeX');
    const crossLineShapeY = this.get('crossLineShapeY');
    const crosshairsRectShape = this.get('crosshairsRectShape');
    const endx = x;
    const endy = y;
    const containerWidth = DomUtil.getWidth(container);
    const containerHeight = DomUtil.getHeight(container);
    let offset = this.get('offset');
    let after = true;

    if (isFixed) {
      x = x - containerWidth / 2;
      y = y - containerHeight - offset;
    } else {
      const width = containerWidth + 2 * offset;
      x = x - width;
      y = y - containerHeight - 2 * offset;
    }

    if (this.get('inPlot')) { // 限定必须展示在图表绘图区域内
      const plotRange = this.get('plotRange');
      const point = {
        x,
        y
      };
      const inPlot = isInPlot(plotRange, point);

      if (!inPlot.inPlot) {
        if (!inPlot.inHorizontal) {
          if ((plotRange.tr.x - plotRange.tl.x) >= 2 * containerWidth) {
            x = Math.max(plotRange.tl.x, endx) + offset;
            after = false;
          } else {
            x = plotRange.tl.x;
            y -= offset;
          }
        }

        if (!inPlot.inVertical) {
          y = plotRange.tl.y;
        }
      }
    }

    if (this.get('x') !== x || this.get('y') !== y) {
      if (crossLineShapeY) { // 第一次进入时，画布需要单独绘制，所以需要先设定corss的位置
        if (after) {
          crossLineShapeY.move(endx, 0);
        } else {
          crossLineShapeY.move((x - offset), 0);
        }
      }
      if (crossLineShapeX) {
        crossLineShapeX.move(0, endy);
      }

      if (crosshairsRectShape) {
        const isTransposed = this.get('isTransposed');
        const items = isTransposed ? this.get('items').reverse() : this.get('items');
        const firstItem = items[0];
        const dim = isTransposed ? 'y' : 'x';
        const attr = isTransposed ? 'height' : 'width';

        if (this.get('crosshairs').width) { // 用户定义了 width
          crosshairsRectShape.attr(dim, firstItem.point[dim] - this.get('crosshairs').width / 2);
          crosshairsRectShape.attr(attr, this.get('crosshairs').width);
        } else {
          offset = (firstItem.size / 2 + firstItem.size / 4) || 10;
          crosshairsRectShape.attr(dim, firstItem.point[dim] - offset);

          if (items.length === 1) {
            crosshairsRectShape.attr(attr, firstItem.size + firstItem.size / 2);
          } else {
            const lastItem = items[items.length - 1];
            crosshairsRectShape.attr(attr, lastItem.point[dim] - firstItem.point[dim] + 2 * offset);
          }
        }
      }

      const follow = this.get('follow');
      container.style.left = follow ? (x + 'px') : 0;
      container.style.top = follow ? (y + 'px') : 0;
    }
  }

  show() {
    const crossLineShapeX = this.get('crossLineShapeX');
    const crossLineShapeY = this.get('crossLineShapeY');
    const crosshairsRectShape = this.get('crosshairsRectShape');
    const markerGroup = this.get('markerGroup');
    const container = this.get('container');
    const hideHandler = this.get('hideHandler');
    const canvas = this.get('canvas');
    if (hideHandler) {
      clearTimeout(hideHandler);
    }
    crossLineShapeX && crossLineShapeX.show();
    crossLineShapeY && crossLineShapeY.show();
    crosshairsRectShape && crosshairsRectShape.show();
    markerGroup && markerGroup.show();
    super.show();
    container.style.visibility = 'visible';
    this.sort();
    canvas.draw();
  }

  hide() {
    const self = this;
    const container = self.get('container');
    const crossLineShapeX = self.get('crossLineShapeX');
    const crossLineShapeY = self.get('crossLineShapeY');
    const crosshairsRectShape = this.get('crosshairsRectShape');
    const markerGroup = self.get('markerGroup');
    const canvas = self.get('canvas');
    const hideHandler = setTimeout(function() {
      container.style.visibility = 'hidden';
      self.set('hideHandler', null);
      if (!self.get('destroyed')) {
        Tooltip.superclass.hide.call(self);
        canvas.draw();
      }
    }, self.get('duration'));
    self.set('hideHandler', hideHandler);
    crossLineShapeX && crossLineShapeX.hide();
    crossLineShapeY && crossLineShapeY.hide();
    crosshairsRectShape && crosshairsRectShape.hide();
    markerGroup && markerGroup.hide();
  }

  remove() {
    const self = this;
    const crossLineShapeX = self.get('crossLineShapeX');
    const crossLineShapeY = self.get('crossLineShapeY');
    const markerGroup = self.get('markerGroup');
    const crosshairsRectShape = self.get('crosshairsRectShape');
    const container = self.get('container');
    const containerTpl = self.get('containerTpl');

    crossLineShapeX && crossLineShapeX.remove();
    crossLineShapeY && crossLineShapeY.remove();
    markerGroup && markerGroup.remove();
    crosshairsRectShape && crosshairsRectShape.remove();
    super.remove();

    if (container && !(/^\#/.test(containerTpl))) {
      container.parentNode.removeChild(container);
    }
  }
}

module.exports = Tooltip;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from '../PropTypes.js';
import Location from '../controls/Location.js';
import Paper from 'material-ui/Paper';

const topSponsorPaperStyle = {
  height: 100,
  width: 250,
  padding: 15,
  display: 'inline-block',
};

const topSponsorsOnBottomPaperStyle = {
  padding: 15,
  width: 220,
  margin: 'auto',
};

export class BakkerijVanLierde extends Component {
  static contextTypes = PropTypes.contextTypes;
  static propTypes = {
    big: PropTypes.bool.isRequired,
  };

  render() {
    const loc = {
      description: 'Brood & banket Van Lierde',
      address: 'Hogeweg 113',
      postalCode: 9320,
      city: 'Erembodegem',
      mobile: '053212720',
    };

    return (
      <Paper style={this.props.big ? {...topSponsorPaperStyle, width: 220} : topSponsorsOnBottomPaperStyle}>
        <Location loc={loc} t={this.context.t} />
      </Paper>
    );
  }
}

export class SlagerijGuy extends Component {
  static contextTypes = PropTypes.contextTypes;
  static propTypes = {
    big: PropTypes.bool.isRequired,
  };

  render() {
    const loc = {
      description: 'Slagerij Guy',
      address: 'Erembodegem Dorp 72',
      postalCode: 9320,
      city: 'Erembodegem',
      mobile: '053211359',
    };

    const style = this.props.big ? {...topSponsorPaperStyle, float: 'right', width: 200} : topSponsorsOnBottomPaperStyle;
    return (
      <Paper style={style}>
        <Location loc={loc} t={this.context.t} />
      </Paper>
    );
  }
}

export const StoneDesign = props => <ImageSponsor url="http://www.stonedesign.be" img="stonedesign.png" {...props} />;
export const Vdhkeukens = props => <ImageSponsor url="http://vdhkeukens.be" img="vdhkeukens.png" {...props} />;
export const Symphony = props => <ImageSponsor url="http://doopsuikersymphony.be" img="symphony.png" {...props} />;
export const pongit = props => <ImageSponsor url="http://pongit.be" img="pongit.jpg" {...props} />;
export const Nostech = props => <ImageSponsor url="http://www.nostech.be" img="nostech.jpg" {...props} />;
export const KachelsTfe = props => <ImageSponsor url="http://www.kachels-tfe.be/" img="kachels-tfe.png" {...props} />;

class ImageSponsor extends Component {
  static propTypes = {
    big: PropTypes.bool.isRequired,
    url: PropTypes.string,
    img: PropTypes.string.isRequired,
    style: PropTypes.object,
  };
  static defaultProps = {
    style: {},
  };

  render() {
    const style = this.props.big ? bottomSponsorsStyleBig : bottomSponsorsStyleSmall;
    const img = ;
    return (
      <Paper style={{...style, ...this.props.style}}>
        {this.props.url ? {img} : img}
      </Paper>
    );
  }
}

const bottomSponsorsStyleBig = {
  padding: 5,
  textAlign: 'center',
  display: 'inline-block'
};

const bottomSponsorsStyleSmall = {
  padding: 15,
  width: '100%',
  textAlign: 'center',
  margin: 'auto',
};
<commit_msg>Sponsors: bugfix that content sometimes overflew their box<commit_after>import React, { Component } from 'react';
import PropTypes from '../PropTypes.js';
import Location from '../controls/Location.js';
import Paper from 'material-ui/Paper';

const topSponsorPaperStyle = {
  height: 100,
  padding: 15,
  display: 'inline-block',
};

const topSponsorsOnBottomPaperStyle = {
  padding: 15,
  width: 300,
  margin: 'auto',
};

export class BakkerijVanLierde extends Component {
  static contextTypes = PropTypes.contextTypes;
  static propTypes = {
    big: PropTypes.bool.isRequired,
  };

  render() {
    const loc = {
      description: 'Brood & banket Van Lierde',
      address: 'Hogeweg 113',
      postalCode: 9320,
      city: 'Erembodegem',
      mobile: '053212720',
    };

    return (
      <Paper style={this.props.big ? {...topSponsorPaperStyle} : topSponsorsOnBottomPaperStyle}>
        <Location loc={loc} t={this.context.t} />
      </Paper>
    );
  }
}

export class SlagerijGuy extends Component {
  static contextTypes = PropTypes.contextTypes;
  static propTypes = {
    big: PropTypes.bool.isRequired,
  };

  render() {
    const loc = {
      description: 'Slagerij Guy',
      address: 'Erembodegem Dorp 72',
      postalCode: 9320,
      city: 'Erembodegem',
      mobile: '053211359',
    };

    const style = this.props.big ? {...topSponsorPaperStyle, float: 'right'} : topSponsorsOnBottomPaperStyle;
    return (
      <Paper style={style}>
        <Location loc={loc} t={this.context.t} />
      </Paper>
    );
  }
}

export const StoneDesign = props => <ImageSponsor url="http://www.stonedesign.be" img="stonedesign.png" {...props} />;
export const Vdhkeukens = props => <ImageSponsor url="http://vdhkeukens.be" img="vdhkeukens.png" {...props} />;
export const Symphony = props => <ImageSponsor url="http://doopsuikersymphony.be" img="symphony.png" {...props} />;
export const pongit = props => <ImageSponsor url="http://pongit.be" img="pongit.jpg" {...props} />;
export const Nostech = props => <ImageSponsor url="http://www.nostech.be" img="nostech.jpg" {...props} />;
export const KachelsTfe = props => <ImageSponsor url="http://www.kachels-tfe.be/" img="kachels-tfe.png" {...props} />;

class ImageSponsor extends Component {
  static propTypes = {
    big: PropTypes.bool.isRequired,
    url: PropTypes.string,
    img: PropTypes.string.isRequired,
    style: PropTypes.object,
  };
  static defaultProps = {
    style: {},
  };

  render() {
    const style = this.props.big ? bottomSponsorsStyleBig : bottomSponsorsStyleSmall;
    const img = ;
    return (
      <Paper style={{...style, ...this.props.style}}>
        {this.props.url ? {img} : img}
      </Paper>
    );
  }
}

const bottomSponsorsStyleBig = {
  padding: 5,
  textAlign: 'center',
  display: 'inline-block'
};

const bottomSponsorsStyleSmall = {
  padding: 15,
  width: '100%',
  textAlign: 'center',
  margin: 'auto',
};
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React from 'react';
import { FormattedMessage, FormattedHTMLMessage, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import Snackbar from '@material-ui/core/Snackbar';
import intl from 'intl';  // eslint-disable-line
import intlEn from 'intl/locale-data/jsonp/en.js';  // eslint-disable-line
import { Row } from 'react-flexbox-grid/lib';
import NavToolbar from './common/header/NavToolbar';
import ErrorBoundary from './common/ErrorBoundary';
import messages from '../resources/messages';
import { getVersion } from '../config';
import { ErrorNotice, WarningNotice } from './common/Notice';
import { assetUrl } from '../lib/assetUtil';
import AppNoticesContainer from './common/header/AppNoticesContainer';

const localMessages = {
  privacyPolicy: { id: 'app.privacyPolicy', defaultMessage: 'Read our privacy policy.' },
  maintenance: { id: 'app.maintenance', defaultMessage: 'Sorry, we have taken our system down right now for maintenance' },
  construction: { id: 'app.construction', defaultMessage: 'Notice, we will be performing system level maintenance Oct 7-8 2019' },
};

class AppContainer extends React.Component {
  state = {
    open: false,
  };

  componentWillReceiveProps(nextProps) {
    const { feedback } = this.props;
    if (nextProps.feedback.message !== feedback.message) {
      this.setState({ open: true });
    }
  }

  handleClose = () => {
    this.setState({ open: false });
  };

  render() {
    const { children, feedback, name } = this.props;

    let content = children;
    const construction = (

        <WarningNotice>

          <FormattedMessage {...localMessages.construction} />

        </WarningNotice>

    );
    if (document.appConfig.online === false) {
      content = (

          <Row center="lg">
            <ErrorNotice>

              <FormattedMessage {...localMessages.maintenance} />

            </ErrorNotice>
          </Row>

      );
    }

    return (
      <div className={`app-container app-${name}`}>
        <AppNoticesContainer />

          <NavToolbar />

        <ErrorBoundary>
          {construction}

            {content}

        </ErrorBoundary>

              {'Created by the '}

                <FormattedMessage {...messages.c4cmName} />

              {' and the '}

                <FormattedMessage {...messages.berkmanName} />
              .

              <FormattedHTMLMessage {...messages.supportOptions} />

              <FormattedHTMLMessage {...localMessages.privacyPolicy} />

              v{getVersion()}

        <Snackbar
          className={feedback.classes ? feedback.classes : 'info_notice'}
          open={this.state.open}
          onClose={this.handleClose}
          message={feedback.message}
          action={feedback.action}
          anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
          autoHideDuration={5000}
        />

    );
  }
}

AppContainer.propTypes = {
  children: PropTypes.node,
  handleTouchTapLeftIconButton: PropTypes.func,
  intl: PropTypes.object.isRequired,
  // from state
  feedback: PropTypes.object.isRequired,
  // from parent
  name: PropTypes.string.isRequired,
  title: PropTypes.string.isRequired,
  description: PropTypes.string.isRequired,
  showLoginButton: PropTypes.bool,
};

AppContainer.contextTypes = {
  router: PropTypes.object.isRequired,
  store: PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
  feedback: state.app.feedback,
});

export default
injectIntl(
  connect(mapStateToProps)(
    AppContainer
  )
);
<commit_msg>#1654<commit_after>import PropTypes from 'prop-types';
import React from 'react';
import { FormattedMessage, FormattedHTMLMessage, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import Snackbar from '@material-ui/core/Snackbar';
import intl from 'intl';  // eslint-disable-line
import intlEn from 'intl/locale-data/jsonp/en.js';  // eslint-disable-line
import { Row } from 'react-flexbox-grid/lib';
import NavToolbar from './common/header/NavToolbar';
import ErrorBoundary from './common/ErrorBoundary';
import messages from '../resources/messages';
import { getVersion } from '../config';
import { ErrorNotice, WarningNotice } from './common/Notice';
import { assetUrl } from '../lib/assetUtil';
import AppNoticesContainer from './common/header/AppNoticesContainer';

const localMessages = {
  privacyPolicy: { id: 'app.privacyPolicy', defaultMessage: 'Read our privacy policy.' },
  maintenance: { id: 'app.maintenance', defaultMessage: 'Sorry, we have taken our system down right now for maintenance' },
  construction: { id: 'app.construction', defaultMessage: 'Notice, we will be performing system-level maintenance Oct 7-8 2019. Expect interruptions in service.' },
};

class AppContainer extends React.Component {
  state = {
    open: false,
  };

  componentWillReceiveProps(nextProps) {
    const { feedback } = this.props;
    if (nextProps.feedback.message !== feedback.message) {
      this.setState({ open: true });
    }
  }

  handleClose = () => {
    this.setState({ open: false });
  };

  render() {
    const { children, feedback, name } = this.props;

    let content = children;
    const construction = (

        <WarningNotice>

          <FormattedMessage {...localMessages.construction} />

        </WarningNotice>

    );
    if (document.appConfig.online === false) {
      content = (

          <Row center="lg">
            <ErrorNotice>

              <FormattedMessage {...localMessages.maintenance} />

            </ErrorNotice>
          </Row>

      );
    }

    return (
      <div className={`app-container app-${name}`}>
        <AppNoticesContainer />

          <NavToolbar />

        <ErrorBoundary>
          {construction}

            {content}

        </ErrorBoundary>

              {'Created by the '}

                <FormattedMessage {...messages.c4cmName} />

              {' and the '}

                <FormattedMessage {...messages.berkmanName} />
              .

              <FormattedHTMLMessage {...messages.supportOptions} />

              <FormattedHTMLMessage {...localMessages.privacyPolicy} />

              v{getVersion()}

        <Snackbar
          className={feedback.classes ? feedback.classes : 'info_notice'}
          open={this.state.open}
          onClose={this.handleClose}
          message={feedback.message}
          action={feedback.action}
          anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
          autoHideDuration={5000}
        />

    );
  }
}

AppContainer.propTypes = {
  children: PropTypes.node,
  handleTouchTapLeftIconButton: PropTypes.func,
  intl: PropTypes.object.isRequired,
  // from state
  feedback: PropTypes.object.isRequired,
  // from parent
  name: PropTypes.string.isRequired,
  title: PropTypes.string.isRequired,
  description: PropTypes.string.isRequired,
  showLoginButton: PropTypes.bool,
};

AppContainer.contextTypes = {
  router: PropTypes.object.isRequired,
  store: PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
  feedback: state.app.feedback,
});

export default
injectIntl(
  connect(mapStateToProps)(
    AppContainer
  )
);
<|endoftext|>