<commit_before>/*
 * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map.
 */

L.Map.mergeOptions({
	scrollWheelZoom: true
});

L.Map.ScrollWheelZoom = L.Handler.extend({
	addHooks: function () {
		L.DomEvent.on(this._map._container, {
			mousewheel: this._onWheelScroll,
			MozMousePixelScroll: L.DomEvent.preventDefault
		}, this);

		this._delta = 0;
	},

	removeHooks: function () {
		L.DomEvent.off(this._map._container, {
			mousewheel: this._onWheelScroll,
			MozMousePixelScroll: L.DomEvent.preventDefault
		}, this);
	},

	_onWheelScroll: function (e) {
		var delta = L.DomEvent.getWheelDelta(e);

		this._delta += delta;
		this._lastMousePos = this._map.mouseEventToContainerPoint(e);

		if (!this._startTime) {
			this._startTime = +new Date();
		}

		var left = Math.max(40 - (+new Date() - this._startTime), 0);

		clearTimeout(this._timer);
		this._timer = setTimeout(L.bind(this._performZoom, this), left);

		L.DomEvent.stop(e);
	},

	_performZoom: function () {
		var map = this._map,
		    delta = this._delta,
		    zoom = map.getZoom();

		delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta);
		delta = Math.max(Math.min(delta, 4), -4);
		delta = map._limitZoom(zoom + delta) - zoom;

		this._delta = 0;
		this._startTime = null;

		if (!delta) { return; }

		if (map.options.scrollWheelZoom === 'center') {
			map.setZoom(zoom + delta);
		} else {
			map.setZoomAround(this._lastMousePos, zoom + delta);
		}
	}
});

L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom);
<commit_msg>#2501, wheelDebounceTime option added<commit_after>/*
 * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map.
 */

L.Map.mergeOptions({
	scrollWheelZoom: true,
	wheelDebounceTime: 40
});

L.Map.ScrollWheelZoom = L.Handler.extend({
	addHooks: function () {
		L.DomEvent.on(this._map._container, {
			mousewheel: this._onWheelScroll,
			MozMousePixelScroll: L.DomEvent.preventDefault
		}, this);

		this._delta = 0;
	},

	removeHooks: function () {
		L.DomEvent.off(this._map._container, {
			mousewheel: this._onWheelScroll,
			MozMousePixelScroll: L.DomEvent.preventDefault
		}, this);
	},

	_onWheelScroll: function (e) {
		var delta = L.DomEvent.getWheelDelta(e),
			debounce = this._map.options.wheelDebounceTime;

		this._delta += delta;
		this._lastMousePos = this._map.mouseEventToContainerPoint(e);

		if (!this._startTime) {
			this._startTime = +new Date();
		}

		var left = Math.max(debounce - (+new Date() - this._startTime), 0);

		clearTimeout(this._timer);
		this._timer = setTimeout(L.bind(this._performZoom, this), left);

		L.DomEvent.stop(e);
	},

	_performZoom: function () {
		var map = this._map,
		    delta = this._delta,
		    zoom = map.getZoom();

		delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta);
		delta = Math.max(Math.min(delta, 4), -4);
		delta = map._limitZoom(zoom + delta) - zoom;

		this._delta = 0;
		this._startTime = null;

		if (!delta) { return; }

		if (map.options.scrollWheelZoom === 'center') {
			map.setZoom(zoom + delta);
		} else {
			map.setZoomAround(this._lastMousePos, zoom + delta);
		}
	}
});

L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom);
<|endoftext|>


<commit_before>(function () {
  'use strict';

  moj.Modules.PrintPageButton = {
    init: function() {
      this.initTemplates();
      this.renderButton();
    },

    renderButton: function() {
      var contentArea = $('.confirmation');

      if(!contentArea.length || !this.printButton || !this.printButton.length) {
        return;
      }

      contentArea.append(this.printButton);

      this.printButton.on('click', function() {
        window.print();
      });
    },

    initTemplates: function() {
      var template = $('#printButtonTemplate');

      if(template.length) {
        this.printButton = $(_.template(template.html())());
      }
    }
  };
}());
<commit_msg>FE: Send GA event when print page button is clicked<commit_after>(function () {
  'use strict';

  moj.Modules.PrintPageButton = {
    init: function() {
      this.initTemplates();
      this.renderButton();
    },

    renderButton: function() {
      var contentArea = $('.confirmation');

      if(!contentArea.length || !this.printButton || !this.printButton.length) {
        return;
      }

      contentArea.append(this.printButton);

      this.printButton.on('click', function() {
        window.print();
        if(window.ga) {
          window.ga('send', 'event', 'confirmation', 'printed');
        }
      });
    },

    initTemplates: function() {
      var template = $('#printButtonTemplate');

      if(template.length) {
        this.printButton = $(_.template(template.html())());
      }
    }
  };
}());
<|endoftext|>


<commit_before>const {React} = Serverboards
// const {colorize} = Serverboards.utils

function is_string(txt){
  return typeof(txt) == "string"
}

const COLORS = [
  "#a333c8",
  "#e03997",
  "#2185d0",
  "#00b5ad",
  "#b5cc18"
]

function colorize(index){
  return COLORS[index % COLORS.length]
}

const STOP_POINTS = [ 10000000, 1000000, 100000, 10000, 1000, 500, 100, 50, 10, 0, -1e100]

function next_stop_point(point){
  let prev = point
  for (const sp of STOP_POINTS){
    console.log("sp", sp, "point", point)
    if (sp < point)
      return prev
    prev = sp
  }
}

function get_data(expr){
  if (!expr)
    return ""
  if (expr.loading){
    return (

    )
  }
  if (expr.error){
    return (

    )
  }
  else if (expr.rows){
    return String(expr.rows[0])
  }
  return String(expr)
}

const svg_style = {
  axis_bottom: {
    fill: "#000"
  },
  axis: {
    fill: "#9b9b9b"
  },
  grey: "#9b9b9b"

}

function SVGBars({data, xaxis, maxy, categories}){
  const xgap = 370.0 / xaxis.length // each categeory group width
  const xgap2 = ((xgap*3)/4)/categories.length // each category width
  const xgap4 = xgap2 / 2
  const xstart = 40 // where starts the  data
  const xstart2 = 40 + xgap2/2 // DELETE old mid line start
  console.log({xgap, xgap2, xstart, xstart2})

  // line colors
  const fill = categories.reduce( (acc, cat, i) => acc.concat(colorize(i)), [])

  function rescale(legend, category){
    const v = data[ [legend, category] ]
    // console.log("Rescale [%o,%o] %o => %o", legend, category, v, (v/maxy)*190.0)
    if (!v)
      return 0
    return (v/maxy)*190.0
  }

  console.log(fill)
  return (
    <svg height={250} width={400}>
      <g>
        <text x={30} y={25} textAnchor="end" fill={svg_style.grey}>{maxy}</text>
        <text x={30} y={75} textAnchor="end" fill={svg_style.grey}>{maxy*3/4}</text>
        <text x={30} y={125} textAnchor="end" fill={svg_style.grey}>{maxy*2/4}</text>
        <text x={30} y={175} textAnchor="end" fill={svg_style.grey}>{maxy/4}</text>
        <text x={30} y={225} textAnchor="end" fill={svg_style.grey}>0</text>
        <line x1={40} y1={220} x2={390} y2={220} style={svg_style.axis_bottom}/>
        {xaxis.map( (legend,i) => (
          <text x={xstart + i*xgap} y={235} style={svg_style.axis}>{legend}</text>
        ))}
      </g>
      <g>
        {xaxis.map( (legend,i) =>
          <g>
            {categories.map( (category, j) => {
              const x1 = xstart + i*xgap + j*xgap2
              const x2 = x1 + xgap2
              const y1 = 220
              const y2 = 220 - rescale(legend, category) - xgap4
              return (
                <g>
                  <path d={`M ${x1} ${y1} L ${x1} ${y2} A ${xgap4} ${xgap4} 0 0 1 ${x2} ${y2} L ${x2} ${y1} Z`} style={{fill: fill[j]}}/>
                </g>

              )
            } )}
          </g>
        ) }
      </g>
    </svg>
  )
}

class Bars extends React.Component {
  render(){
    const props = this.props
    const config = props.config

    console.log(config)

    const performance = get_data(config.performance)
    let performance_color = ""
    if (is_string(performance) && performance.startsWith('-'))
      performance_color = 'red'
    if (is_string(performance) && performance.startsWith('+'))
      performance_color = 'teal'

    const categories = Array.from(new Set(config.data.rows.map( r => r[0] )))
    const xaxis = Array.from(new Set(config.data.rows.map( r => r[1] ))).sort()
    const maxy = next_stop_point(config.data.rows.reduce( (acc, r) => Math.max(acc, Number(r[2])), 0 ))
    const data = config.data.rows.reduce( (acc, r) => {acc[ [r[1], r[0]] ] = Number(r[2]); return acc}, {})

    console.log(categories, xaxis, maxy, data)
    return (

          <SVGBars data={data} xaxis={xaxis} maxy={maxy} categories={categories}/>

{get_data(config.summary)}

          <div className={`ui ${performance_color} text`}>{performance}

            {categories.map( (c, i) => (

                <span className={`ui square`} style={{background: colorize(i)}}/>
                {c}

            ))}

    )
  }
}

Serverboards.add_widget("serverboards.core.widgets/bars", Bars, {react: true})
<commit_msg>If bar size is zero, do not show<commit_after>const {React} = Serverboards
// const {colorize} = Serverboards.utils

function is_string(txt){
  return typeof(txt) == "string"
}

const COLORS = [
  "#a333c8",
  "#e03997",
  "#2185d0",
  "#00b5ad",
  "#b5cc18"
]

function colorize(index){
  return COLORS[index % COLORS.length]
}

const STOP_POINTS = [ 10000000, 1000000, 100000, 10000, 1000, 500, 100, 50, 10, 0, -1e100]

function next_stop_point(point){
  let prev = point
  for (const sp of STOP_POINTS){
    console.log("sp", sp, "point", point)
    if (sp < point)
      return prev
    prev = sp
  }
}

function get_data(expr){
  if (!expr)
    return ""
  if (expr.loading){
    return (

    )
  }
  if (expr.error){
    return (

    )
  }
  else if (expr.rows){
    return String(expr.rows[0])
  }
  return String(expr)
}

const svg_style = {
  axis_bottom: {
    fill: "#000"
  },
  axis: {
    fill: "#9b9b9b"
  },
  grey: "#9b9b9b"

}

function SVGBars({data, xaxis, maxy, categories}){
  const xgap = 370.0 / xaxis.length // each categeory group width
  const xgap2 = ((xgap*3)/4)/categories.length // each category width
  const xgap4 = xgap2 / 2
  const xstart = 40 // where starts the  data
  const xstart2 = 40 + xgap2/2 // DELETE old mid line start
  console.log({xgap, xgap2, xstart, xstart2})

  // line colors
  const fill = categories.reduce( (acc, cat, i) => acc.concat(colorize(i)), [])

  function rescale(legend, category){
    const v = data[ [legend, category] ]
    // console.log("Rescale [%o,%o] %o => %o", legend, category, v, (v/maxy)*190.0)
    if (!v)
      return 0
    return (v/maxy)*190.0
  }

  console.log(fill)
  return (
    <svg height={250} width={400}>
      <g>
        <text x={30} y={25} textAnchor="end" fill={svg_style.grey}>{maxy}</text>
        <text x={30} y={75} textAnchor="end" fill={svg_style.grey}>{maxy*3/4}</text>
        <text x={30} y={125} textAnchor="end" fill={svg_style.grey}>{maxy*2/4}</text>
        <text x={30} y={175} textAnchor="end" fill={svg_style.grey}>{maxy/4}</text>
        <text x={30} y={225} textAnchor="end" fill={svg_style.grey}>0</text>
        <line x1={40} y1={220} x2={390} y2={220} style={svg_style.axis_bottom}/>
        {xaxis.map( (legend,i) => (
          <text x={xstart + i*xgap} y={235} style={svg_style.axis}>{legend}</text>
        ))}
      </g>
      <g>
        {xaxis.map( (legend,i) =>
          <g>
            {categories.map( (category, j) => {
              const x1 = xstart + i*xgap + j*xgap2
              const x2 = x1 + xgap2
              const y1 = 220
              const y2 = 220 - Math.max(0, rescale(legend, category) - xgap4)
              if (y2 == y1)
                return null
              return (
                <path d={`M ${x1} ${y1} L ${x1} ${y2} A ${xgap4} ${xgap4} 0 0 1 ${x2} ${y2} L ${x2} ${y1} Z`} style={{fill: fill[j]}}/>

              )
            } )}
          </g>
        ) }
      </g>
    </svg>
  )
}

class Bars extends React.Component {
  render(){
    const props = this.props
    const config = props.config

    console.log(config)

    const performance = get_data(config.performance)
    let performance_color = ""
    if (is_string(performance) && performance.startsWith('-'))
      performance_color = 'red'
    if (is_string(performance) && performance.startsWith('+'))
      performance_color = 'teal'

    const categories = Array.from(new Set(config.data.rows.map( r => r[0] )))
    const xaxis = Array.from(new Set(config.data.rows.map( r => r[1] ))).sort()
    const maxy = next_stop_point(config.data.rows.reduce( (acc, r) => Math.max(acc, Number(r[2])), 0 ))
    const data = config.data.rows.reduce( (acc, r) => {acc[ [r[1], r[0]] ] = Number(r[2]); return acc}, {})

    console.log(categories, xaxis, maxy, data)
    return (

          <SVGBars data={data} xaxis={xaxis} maxy={maxy} categories={categories}/>

{get_data(config.summary)}

          <div className={`ui ${performance_color} text`}>{performance}

            {categories.map( (c, i) => (

                <span className={`ui square`} style={{background: colorize(i)}}/>
                {c}

            ))}

    )
  }
}

Serverboards.add_widget("serverboards.core.widgets/bars", Bars, {react: true})
<|endoftext|>


<commit_before>$(function() {
    window.onload = function() {
    console.log("%c  ~~~  Bob v0.5 - Developed by d4rkd0s & d3mn5pwn ~~~  ", "color: #FFFFFF; font-size: 12px; background: #3F1338;");
    var game = new Phaser.Game(1156, 650, Phaser.CANVAS, '', { preload: preload, create: create, update: update, render: render });
    function preload() {
        //setting up starting vars
        apple_count = 1;
        score = 0;
        console.log("%c   score: 0   ", "color: #FFFFFF; font-size: 12px; background: #FD8223;");
        horseHealth = 10;
        console.log("%c   horseHealth: 10   ", "color: #FFFFFF; font-size: 12px; background: #FD8223;");

        speed = 250;
        //game.load.image('bob', 'assets/images/bob.png');
        game.load.spritesheet('bob', 'assets/images/bob.png', 54, 80);
        console.log("%c   loaded: spritesheet   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        game.load.image('apple', 'assets/images/apple_red.png');
        game.load.image('tree', 'assets/images/tree.png');
        game.load.image('sun', 'assets/images/sun.png');
        game.load.image('background', 'assets/images/background.png');
        console.log("%c   loaded: background   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        //game.load.image('healthbar', 'assets/images/healthbar.png');
        //console.log("%c   loaded: healthbar   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        game.load.image('ocean', 'assets/images/ocean.png');
        console.log("%c   loaded: horse   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        game.load.image('horse', 'assets/images/horse.png');
        console.log("%c   set border: ocean   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        cursors = game.input.keyboard.createCursorKeys();
        console.log("%c   user input: enabled   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        game.load.audio('applesound', 'assets/sounds/apple.wav');
        game.load.audio('bobsound', 'assets/sounds/bob.wav')
        //walking case switch
        function coroutine(f) {
           var o = f(); // instantiate the coroutine
           o.next(); // execute until the first yield
           return function(x) {
                o.next(x);
            }
        }
        var clock = coroutine(function*(_) {
            while (true) {
                yield _;
                foot = 0;
                yield _;
                foot = 1;
            }
        });

        //walk step speed in ms
        setInterval(clock, 100);
        //notify user (console)
        console.log("%c   walking: enabled   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
    }//preload

    function create() {

        //  A simple background for our game
        game.add.sprite(0, 0, 'background');
        console.log("%c   spawned: background   ", "color: #FFFFFF; font-size: 10px; background: #FCD22F;");
        //Game Objects

        apple = game.add.sprite(100, 200, 'apple');
        appleOnTree = 0;
        // Stretch to fill
        game.scale.fullScreenScaleMode = Phaser.ScaleManager.EXACT_FIT;

        //var healthbar = game.add.sprite(0,0,'healthbar');
        //healthbar.cropEnabled = true;
        //healthbar.crop.width = (character.health / character.maxHealth) * healthbar.width

        //text = "Score: " . score;
        //style = { font: "32px Arial", fill: "#3D4185", align: "center" };
        //game.add.text(game.world.centerX-300, 0, text, style);
        //sound
        applesound = game.add.audio('applesound');
        applesound.allowMultiple = true;

        bobsound = game.add.audio('bobsound');
        bobsound.allowMultiple = true;

        ocean = game.add.sprite(0, game.world.height - 484, 'ocean');
        tree = game.add.sprite(450, 30, 'tree');
        console.log("%c   spawned: border(ocean)   ", "color: #FFFFFF; font-size: 10px; background: #FCD22F;");

        //add horse
        horse = game.add.sprite(450, game.world.height - 300, 'horse');

        //add horse
        sun = game.add.sprite(80, 20, 'sun');

        //add player
        player = game.add.sprite(775, game.world.height - 150, 'bob');
        console.log("%c   spawned: player   ", "color: #FFFFFF; font-size: 10px; background: #FCD22F;");
        //ocean
        game.physics.enable(ocean, Phaser.Physics.ARCADE);
        console.log("%c   physics: enabled(ocean)   ", "color: #FFFFFF; font-size: 10px; background: #83CB53;");
        ocean.body.immovable = true;
        console.log("%c   locked: border(ocean)   ", "color: #FFFFFF; font-size: 10px; background: #A40E38;");

        //start physics
        game.physics.startSystem(Phaser.Physics.ARCADE);
        console.log("%c   physics: enabled(player)   ", "color: #FFFFFF; font-size: 10px; background: #83CB53;");
        game.physics.arcade.enable(player);
        game.physics.arcade.enableBody(player);
        console.log("%c   physics: bounds(player)   ", "color: #FFFFFF; font-size: 10px; background: #83CB53;");
        game.physics.arcade.enable(horse);
        game.physics.arcade.enableBody(horse);
        game.physics.arcade.enable(apple);
        game.physics.arcade.enableBody(apple);
        player.body.collideWorldBounds = true;
        horse.body.collideWorldBounds = true;
        apple.body.collideWorldBounds = true;
        console.log("%c   collideWorldBounds: enabled   ", "color: #FFFFFF; font-size: 10px; background: #83CB53;");
        horse.anchor.x = 0.5;
        horse.anchor.y = 0.5;

    game.scale.enterFullScreen.add(onEnterFullScreen, this);
    game.scale.leaveFullScreen.add(onLeaveFullScreen, this);

    game.input.onDown.add(gofull, this);

    //prime that apple
    apple.kill();
    }//create

    function onEnterFullScreen() {

        //do anything you want

    }

    function onLeaveFullScreen() {

        //do anything you want

    }

    function gofull() {

        game.scale.startFullScreen();

    }

    function update() {
        console.log(game.time.totalElapsedSeconds());
        apple.bringToTop();
        //ocean collision
        game.physics.arcade.collide(player, ocean);
        game.physics.arcade.collide(player, horse);
        game.physics.arcade.collide(ocean, apple);
        game.physics.arcade.collide(horse, ocean);
        //horse.body.accelerateToObject(horse, player, 600, 250, 250);

        //  Reset the players velocity (movement)
        player.body.velocity.x = 0;
        player.body.velocity.y = 0;

        //bob faster as he scores
        speed = 200+(10*score);

        //move mr.horse
        horse.velocity = game.physics.arcade.accelerateToObject(horse, apple, 50+(score*5), 50+(score*5), 50+(score*5));

        if ( player.y < 250 ) {
            tree.bringToTop();
            apple.bringToTop();
        }
        else{
            player.bringToTop();
        }

        if ( apple.alive == true){
            if ( appleSpawnTime+3 < curTime  && appleOnTree == 0 ){
                appleOnTree = 1;
                console.log("Apple ready to fling!");
            }
            if ( game.physics.arcade.overlap(apple, player) == true && appleOnTree == 1 ){
                score = score + 1;
                bobsound.play();
                $( "#score" ).text("Score: " + score);
                apple.kill();
                console.log("Score: " + score);
            }
            if ( game.physics.arcade.collide(apple, horse) == true && appleOnTree == 1 ){
                horseHealth = horseHealth - 1;
                if ( horseHealth == 1 ){
                    $( "#horseHealth" ).text(horseHealth + " apple until your horse dies!");
                }
                else{
                    $( "#horseHealth" ).text(horseHealth + " apples until your horse dies!");
                }
                applesound.play();
                apple.kill();
                if ( horseHealth == 0 ){
                    $( "#score" ).text("Final Score: " + score);
                    $( "#horseHealth" ).text("Your horse has died!");
                    game.debug.text('Retry? (Refresh the page)', (game.width/2)-140, game.height/2);
                    game.physics.destroy();
                }
                console.log("horseHealth: " + horseHealth);
            }
        }//apple alive
        else{
            if ( apple_count > 0 ){
                randX = Math.floor(Math.random()*(650-600+1)+600);
                randY = Math.floor(Math.random()*(190-90+1)+90);

                console.log("Apple is clear of horse, spawned apple.");
                apple = game.add.sprite(randX, randY, 'apple');
                var appleOnTree = 1;
                var appleSpawnTime = game.time.totalElapsedSeconds();
                console.log(appleSpawnTime);
                game.physics.arcade.enable(apple);
                game.physics.arcade.enableBody(apple);
                apple.body.collideWorldBounds = true;
                game.physics.arcade.collide(player, apple);
                game.physics.arcade.collide(ocean, apple);
            }//apple_count isnt 0
            else {
                console.log("apple count is now zero!");
                game.debug.text('Retry? (Refresh the page)', (game.width/2)-140, game.height/2);
                game.physics.destroy();
            }//apple count is 0
        }//dead apple

        if (cursors.left.isDown)
        {
            if (cursors.up.isDown)
            {
                //  Move to the left+up
                player.body.velocity.x = -speed;
                player.body.velocity.y = -speed;
                if ( foot == 0 ){
                    player.frame = 4;
                }
                if ( foot == 1 ){
                   player.frame = 5;
                }
            }
            else if (cursors.down.isDown)
            {
                //  Move to the left+down
                player.body.velocity.x = -speed;
                player.body.velocity.y = speed;
                if ( foot == 0 ){
                    player.frame = 4;
                }
                if ( foot == 1 ){
                   player.frame = 5;
                }
            }
            else
            {
                //  Move to the left
                player.body.velocity.x = -speed*2;
                if ( foot == 0 ){
                    player.frame = 4;
                }
                if ( foot == 1 ){
                   player.frame = 5;
                }
            }

        }

        else if (cursors.right.isDown)
        {
            if (cursors.up.isDown)
            {
                //  Move to the right+up
                player.body.velocity.x = speed;
                player.body.velocity.y = -speed;
                if ( foot == 0 ){
                    player.frame = 6;
                }
                if ( foot == 1 ){
                   player.frame = 7;
                }
            }
            else if (cursors.down.isDown)
            {
                //  Move to the right+down
                player.body.velocity.x = speed;
                player.body.velocity.y = speed;
                if ( foot == 0 ){
                    player.frame = 6;
                }
                if ( foot == 1 ){
                   player.frame = 7;
                }
            }
            else
            {
                //  Move to the right
                player.body.velocity.x = speed*2;
                if ( foot == 0 ){
                    player.frame = 6;
                }
                if ( foot == 1 ){
                   player.frame = 7;
                }
            }

        }
        else if (cursors.up.isDown)
        {
            //  Move to the up
            player.body.velocity.y = -speed;
            if ( foot == 0 ){
               player.frame = 2;
            }
            if ( foot == 1 ){
               player.frame = 3;
            }
        }
        else if (cursors.down.isDown)
        {
            //  Move to the down
            player.body.velocity.y = speed;
            if ( foot == 0 ){
               player.frame = 0;
            }
            if ( foot == 1 ){
               player.frame = 1;
            }

        }

        } //update

function render () {

    if (game.scale.isFullScreen)
    {
        game.debug.text('ESC to leave fullscreen', (game.width/2)-140, 60);
    }
    else
    {
        game.debug.text('Click / Tap to go fullscreen', (game.width/2)-140, 16);
    }

}
};
});<commit_msg>Wrong line<commit_after>$(function() {
    window.onload = function() {
    console.log("%c  ~~~  Bob v0.5 - Developed by d4rkd0s & d3mn5pwn ~~~  ", "color: #FFFFFF; font-size: 12px; background: #3F1338;");
    var game = new Phaser.Game(1156, 650, Phaser.CANVAS, '', { preload: preload, create: create, update: update, render: render });
    function preload() {
        //setting up starting vars
        apple_count = 1;
        score = 0;
        console.log("%c   score: 0   ", "color: #FFFFFF; font-size: 12px; background: #FD8223;");
        horseHealth = 10;
        console.log("%c   horseHealth: 10   ", "color: #FFFFFF; font-size: 12px; background: #FD8223;");

        speed = 250;
        //game.load.image('bob', 'assets/images/bob.png');
        game.load.spritesheet('bob', 'assets/images/bob.png', 54, 80);
        console.log("%c   loaded: spritesheet   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        game.load.image('apple', 'assets/images/apple_red.png');
        game.load.image('tree', 'assets/images/tree.png');
        game.load.image('sun', 'assets/images/sun.png');
        game.load.image('background', 'assets/images/background.png');
        console.log("%c   loaded: background   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        //game.load.image('healthbar', 'assets/images/healthbar.png');
        //console.log("%c   loaded: healthbar   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        game.load.image('ocean', 'assets/images/ocean.png');
        console.log("%c   loaded: horse   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        game.load.image('horse', 'assets/images/horse.png');
        console.log("%c   set border: ocean   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        cursors = game.input.keyboard.createCursorKeys();
        console.log("%c   user input: enabled   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
        game.load.audio('applesound', 'assets/sounds/apple.wav');
        game.load.audio('bobsound', 'assets/sounds/bob.wav')
        //walking case switch
        function coroutine(f) {
           var o = f(); // instantiate the coroutine
           o.next(); // execute until the first yield
           return function(x) {
                o.next(x);
            }
        }
        var clock = coroutine(function*(_) {
            while (true) {
                yield _;
                foot = 0;
                yield _;
                foot = 1;
            }
        });

        //walk step speed in ms
        setInterval(clock, 100);
        //notify user (console)
        console.log("%c   walking: enabled   ", "color: #FFFFFF; font-size: 10px; background: #5CA6FF;");
    }//preload

    function create() {

        //  A simple background for our game
        game.add.sprite(0, 0, 'background');
        console.log("%c   spawned: background   ", "color: #FFFFFF; font-size: 10px; background: #FCD22F;");
        //Game Objects

        apple = game.add.sprite(100, 200, 'apple');
        appleOnTree = 0;
        // Stretch to fill
        game.scale.fullScreenScaleMode = Phaser.ScaleManager.EXACT_FIT;

        //var healthbar = game.add.sprite(0,0,'healthbar');
        //healthbar.cropEnabled = true;
        //healthbar.crop.width = (character.health / character.maxHealth) * healthbar.width

        //text = "Score: " . score;
        //style = { font: "32px Arial", fill: "#3D4185", align: "center" };
        //game.add.text(game.world.centerX-300, 0, text, style);
        //sound
        applesound = game.add.audio('applesound');
        applesound.allowMultiple = true;

        bobsound = game.add.audio('bobsound');
        bobsound.allowMultiple = true;

        ocean = game.add.sprite(0, game.world.height - 484, 'ocean');
        tree = game.add.sprite(450, 30, 'tree');
        console.log("%c   spawned: border(ocean)   ", "color: #FFFFFF; font-size: 10px; background: #FCD22F;");

        //add horse
        horse = game.add.sprite(450, game.world.height - 300, 'horse');

        //add horse
        sun = game.add.sprite(80, 20, 'sun');

        //add player
        player = game.add.sprite(775, game.world.height - 150, 'bob');
        console.log("%c   spawned: player   ", "color: #FFFFFF; font-size: 10px; background: #FCD22F;");
        //ocean
        game.physics.enable(ocean, Phaser.Physics.ARCADE);
        console.log("%c   physics: enabled(ocean)   ", "color: #FFFFFF; font-size: 10px; background: #83CB53;");
        ocean.body.immovable = true;
        console.log("%c   locked: border(ocean)   ", "color: #FFFFFF; font-size: 10px; background: #A40E38;");

        //start physics
        game.physics.startSystem(Phaser.Physics.ARCADE);
        console.log("%c   physics: enabled(player)   ", "color: #FFFFFF; font-size: 10px; background: #83CB53;");
        game.physics.arcade.enable(player);
        game.physics.arcade.enableBody(player);
        console.log("%c   physics: bounds(player)   ", "color: #FFFFFF; font-size: 10px; background: #83CB53;");
        game.physics.arcade.enable(horse);
        game.physics.arcade.enableBody(horse);
        game.physics.arcade.enable(apple);
        game.physics.arcade.enableBody(apple);
        player.body.collideWorldBounds = true;
        horse.body.collideWorldBounds = true;
        apple.body.collideWorldBounds = true;
        console.log("%c   collideWorldBounds: enabled   ", "color: #FFFFFF; font-size: 10px; background: #83CB53;");
        horse.anchor.x = 0.5;
        horse.anchor.y = 0.5;

    game.scale.enterFullScreen.add(onEnterFullScreen, this);
    game.scale.leaveFullScreen.add(onLeaveFullScreen, this);

    game.input.onDown.add(gofull, this);

    //prime that apple
    apple.kill();
    }//create

    function onEnterFullScreen() {

        //do anything you want

    }

    function onLeaveFullScreen() {

        //do anything you want

    }

    function gofull() {

        game.scale.startFullScreen();

    }

    function update() {
        var curTime = game.time.totalElapsedSeconds();
        apple.bringToTop();
        //ocean collision
        game.physics.arcade.collide(player, ocean);
        game.physics.arcade.collide(player, horse);
        game.physics.arcade.collide(ocean, apple);
        game.physics.arcade.collide(horse, ocean);
        //horse.body.accelerateToObject(horse, player, 600, 250, 250);

        //  Reset the players velocity (movement)
        player.body.velocity.x = 0;
        player.body.velocity.y = 0;

        //bob faster as he scores
        speed = 200+(10*score);

        //move mr.horse
        horse.velocity = game.physics.arcade.accelerateToObject(horse, apple, 50+(score*5), 50+(score*5), 50+(score*5));

        if ( player.y < 250 ) {
            tree.bringToTop();
            apple.bringToTop();
        }
        else{
            player.bringToTop();
        }

        if ( apple.alive == true){
            if ( appleSpawnTime+3 < curTime  && appleOnTree == 0 ){
                appleOnTree = 1;
                console.log("Apple ready to fling!");
            }
            if ( game.physics.arcade.overlap(apple, player) == true && appleOnTree == 1 ){
                score = score + 1;
                bobsound.play();
                $( "#score" ).text("Score: " + score);
                apple.kill();
                console.log("Score: " + score);
            }
            if ( game.physics.arcade.collide(apple, horse) == true && appleOnTree == 1 ){
                horseHealth = horseHealth - 1;
                if ( horseHealth == 1 ){
                    $( "#horseHealth" ).text(horseHealth + " apple until your horse dies!");
                }
                else{
                    $( "#horseHealth" ).text(horseHealth + " apples until your horse dies!");
                }
                applesound.play();
                apple.kill();
                if ( horseHealth == 0 ){
                    $( "#score" ).text("Final Score: " + score);
                    $( "#horseHealth" ).text("Your horse has died!");
                    game.debug.text('Retry? (Refresh the page)', (game.width/2)-140, game.height/2);
                    game.physics.destroy();
                }
                console.log("horseHealth: " + horseHealth);
            }
        }//apple alive
        else{
            if ( apple_count > 0 ){
                randX = Math.floor(Math.random()*(650-600+1)+600);
                randY = Math.floor(Math.random()*(190-90+1)+90);

                console.log("Apple is clear of horse, spawned apple.");
                apple = game.add.sprite(randX, randY, 'apple');
                var appleOnTree = 1;
                var appleSpawnTime = game.time.totalElapsedSeconds();
                console.log(appleSpawnTime);
                game.physics.arcade.enable(apple);
                game.physics.arcade.enableBody(apple);
                apple.body.collideWorldBounds = true;
                game.physics.arcade.collide(player, apple);
                game.physics.arcade.collide(ocean, apple);
            }//apple_count isnt 0
            else {
                console.log("apple count is now zero!");
                game.debug.text('Retry? (Refresh the page)', (game.width/2)-140, game.height/2);
                game.physics.destroy();
            }//apple count is 0
        }//dead apple

        if (cursors.left.isDown)
        {
            if (cursors.up.isDown)
            {
                //  Move to the left+up
                player.body.velocity.x = -speed;
                player.body.velocity.y = -speed;
                if ( foot == 0 ){
                    player.frame = 4;
                }
                if ( foot == 1 ){
                   player.frame = 5;
                }
            }
            else if (cursors.down.isDown)
            {
                //  Move to the left+down
                player.body.velocity.x = -speed;
                player.body.velocity.y = speed;
                if ( foot == 0 ){
                    player.frame = 4;
                }
                if ( foot == 1 ){
                   player.frame = 5;
                }
            }
            else
            {
                //  Move to the left
                player.body.velocity.x = -speed*2;
                if ( foot == 0 ){
                    player.frame = 4;
                }
                if ( foot == 1 ){
                   player.frame = 5;
                }
            }

        }

        else if (cursors.right.isDown)
        {
            if (cursors.up.isDown)
            {
                //  Move to the right+up
                player.body.velocity.x = speed;
                player.body.velocity.y = -speed;
                if ( foot == 0 ){
                    player.frame = 6;
                }
                if ( foot == 1 ){
                   player.frame = 7;
                }
            }
            else if (cursors.down.isDown)
            {
                //  Move to the right+down
                player.body.velocity.x = speed;
                player.body.velocity.y = speed;
                if ( foot == 0 ){
                    player.frame = 6;
                }
                if ( foot == 1 ){
                   player.frame = 7;
                }
            }
            else
            {
                //  Move to the right
                player.body.velocity.x = speed*2;
                if ( foot == 0 ){
                    player.frame = 6;
                }
                if ( foot == 1 ){
                   player.frame = 7;
                }
            }

        }
        else if (cursors.up.isDown)
        {
            //  Move to the up
            player.body.velocity.y = -speed;
            if ( foot == 0 ){
               player.frame = 2;
            }
            if ( foot == 1 ){
               player.frame = 3;
            }
        }
        else if (cursors.down.isDown)
        {
            //  Move to the down
            player.body.velocity.y = speed;
            if ( foot == 0 ){
               player.frame = 0;
            }
            if ( foot == 1 ){
               player.frame = 1;
            }

        }

        } //update

function render () {

    if (game.scale.isFullScreen)
    {
        game.debug.text('ESC to leave fullscreen', (game.width/2)-140, 60);
    }
    else
    {
        game.debug.text('Click / Tap to go fullscreen', (game.width/2)-140, 16);
    }

}
};
});<|endoftext|>


<commit_before>/*
  Generate test objects.
*/
export function addonFactory(kwargs) {
  return Object.assign({}, {
    mini_manifest_url: 'http://testmanifest.com',
    name: 'Test Firefox OS Addon',
    slug: 'test-addon',
  }, kwargs);
}

export function versionFactory(kwargs) {
  return Object.assign({}, {
    id: 1,
    download_url: 'http://testmanifest.com',
    status: 'pending',
    unsigned_download_url: 'http://testmanifest.com',
    version: '1.0',
  }, kwargs);
}

export function versionsFactory() {
  return [
    versionFactory(),
    versionFactory({id: 2, version: '2.0'}),
  ];
}
<commit_msg>update factories<commit_after>/*
  Generate test objects.
*/
export function addonFactory(kwargs) {
  return Object.assign({}, {
    latest_public_version: versionFactory(),
    latest_version: versionFactory(),
    mini_manifest_url: 'http://testmanifest.com',
    name: 'Test Firefox OS Addon',
    slug: 'test-addon',
  }, kwargs);
}

export function versionFactory(kwargs) {
  return Object.assign({}, {
    id: 1,
    download_url: 'http://testmanifest.com',
    status: 'pending',
    unsigned_download_url: 'http://testmanifest.com',
    version: '1.0',
  }, kwargs);
}

export function versionsFactory() {
  return [
    versionFactory(),
    versionFactory({id: 2, version: '2.0'}),
  ];
}
<|endoftext|>


<commit_before>App.tokenizeCard = function( card, complete ) {
console.log('App.tokenizeCard');
	var processor = ( App.config.processor && App.config.processor.type ) ? App.config.processor.type : false;
console.log('processor',processor);
	var legacy_card = {
		card_number: card.number,
		expiration_month: card.expiration_month,
		expiration_year: card.expiration_year,
		security_code: null
	};

	if (App.isPhoneGap) {
		card = legacy_card;
	}

	switch(processor) {
		case 'stripe':
			App.tokenizeCard_stripe( legacy_card, complete );
			break;
		case 'balanced':
			App.tokenizeCard_balanced( card, complete );
		break;
		default:
			console.log( 'Processor error::', App.config.processor );
		break;
	}
};

App.tokenizeCard_stripe = function( card, complete ) {
	var res = { status: false };
	var card = { number: card.card_number, exp_month: card.expiration_month, exp_year: card.expiration_year };
	Stripe.card.createToken( card , function( status, response ){
		if ( response.error ) {
			switch( response.error.code ){
				case 'incorrect_number':
					res.error = 'This card number looks invalid';
					break;
				case 'invalid_number':
					res.error = 'The card number is not a valid credit card number.';
					break;
				case 'invalid_expiry_month':
					res.error = 'The card\'s expiration month is invalid.';
					break;
				case 'invalid_expiry_year':
					res.error = 'The card\'s expiration year is invalid.';
					break;
				case 'invalid_cvc':
					res.error = 'The card\'s security code is invalid.';
					break;
				case 'expired_card':
					res.error = 'The card has expired.';
					break;
				case 'incorrect_cvc':
					res.error = 'The card\'s security code is incorrect.';
					break;
				case 'card_declined':
					res.error = 'The card was declined.';
					break;
				case 'processing_error':
					res.error = 'An error occurred while processing the card.';
					break;
				default:
					console.debug('STRIPE ERROR', card, response);
					res.error = 'Unable to validate your card at this time';
					break;
			}
		} else {
			res = {
				id : response.card.id,
				uri: response.id,
				lastfour: response.card.last4,
				card_type: response.card.type,
				month: response.card.exp_month,
				year: response.card.exp_year,
				status : true
			}
		}
		complete( res );
	} );
};

App.tokenizeCard_balanced = function(card, completed) {

	var handleResponse = function(response) {
		var res = {
			status: false
		};

		// 1.1 to 1.0 migration
		if (response.status_code) {
			var version = '1.1';
			response.status = response.status_code;
		} else {
			var version = '1';
		}

		switch (response.status) {
			case 201:
				res.status = true;
				if (version == '1.1') {
					res.id = response.cards[0].id;
					res.uri = response.cards[0].href;
					if( response.card_type ){
						res.card_type = response.card_type;
					} else {
						res.card_type = getCardType(card.number);
					}
					if( response.last_four ){
						res.lastfour = response.last_four;
					} else {
						res.lastfour = card.number.substr(-4);
					}
				} else {
					res.id = response.data.id;
					res.uri = response.data.uri;
					res.card_type = response.data.card_type;
					res.lastfour = response.data.last_four;
				}

				res.month = card.expiration_month;
				res.year = card.expiration_year;
				break;

			case 400:
				res.error = 'Missing card information';
				break;

			case 402:
				res.error = 'Unable to authorize card';
				break;

			case 404:
				res.error = 'Unexpected payment error';
				break;

			case 409:
				res.error = 'Unable to validate credit card';
				break;

			case 500:
				res.error = 'Error processing payment';
				break;

			// a lack of any response from the ios sdk
			case 999:
				res.error = 'Unable to reach payment server';
				break;

			// a response from the ios sdk that was both ilformated and didnt not validate
			case 666:
				res.error = 'Unable to validate your card';
				break;

			// who knows wtf this is
			default:
				console.debug('BALANCED ERROR', card, response);
				res.error = 'Unable to validate your card at this time';
				break;
		}
		completed(res);
	};

	balanced.card.create(card, handleResponse);
};
<commit_msg>partial #4146<commit_after>App.tokenizeCard = function( card, complete ) {
console.log('App.tokenizeCard');
	var processor = ( App.config.processor && App.config.processor.type ) ? App.config.processor.type : false;
console.log('processor',processor);
	var legacy_card = {
		card_number: card.number,
		expiration_month: card.expiration_month,
		expiration_year: card.expiration_year,
		security_code: null
	};

	if (App.isPhoneGap) {
		card = legacy_card;
	}

	switch(processor) {
		case 'stripe':
			App.tokenizeCard_stripe( legacy_card, complete );
			break;
		case 'balanced':
			App.tokenizeCard_balanced( card, complete );
		break;
		default:
			console.log( 'Processor error::', App.config.processor );
		break;
	}
};

App.tokenizeCard_stripe = function( card, complete ) {
	var res = { status: false };
	var card = { number: card.card_number, exp_month: card.expiration_month, exp_year: card.expiration_year };
	Stripe.card.createToken( card , function( status, response ){
		if ( response.error ) {
			switch( response.error.code ){
				case 'incorrect_number':
					res.error = 'This card number looks invalid';
					break;
				case 'invalid_number':
					res.error = 'The card number is not a valid credit card number.';
					break;
				case 'invalid_expiry_month':
					res.error = 'The card\'s expiration month is invalid.';
					break;
				case 'invalid_expiry_year':
					res.error = 'The card\'s expiration year is invalid.';
					break;
				case 'invalid_cvc':
					res.error = 'The card\'s security code is invalid.';
					break;
				case 'expired_card':
					res.error = 'The card has expired.';
					break;
				case 'incorrect_cvc':
					res.error = 'The card\'s security code is incorrect.';
					break;
				case 'card_declined':
					res.error = 'The card was declined.';
					break;
				case 'processing_error':
					res.error = 'An error occurred while processing the card.';
					break;
				default:
					console.debug('STRIPE ERROR', card, response);
					res.error = 'Unable to validate your card at this time';
					break;
			}
		} else {
			res = {
				id : response.card.id,
				uri: response.id,
				lastfour: response.card.last4,
				card_type: response.card.type,
				month: response.card.exp_month,
				year: response.card.exp_year,
				status : true
			}
		}
		complete( res );
	} );
};

App.tokenizeCard_balanced = function(card, completed) {

	var handleResponse = function(response) {
		var res = {
			status: false
		};

		// 1.1 to 1.0 migration
		if (response.status_code) {
			var version = '1.1';
			response.status = response.status_code;
		} else {
			var version = '1';
		}

		switch (response.status) {
			case 201:
				res.status = true;
				if (version == '1.1') {
					res.id = response.cards[0].id;
					res.uri = response.cards[0].href;
					if( response.card_type ){
						res.card_type = response.card_type;
					} else {
						res.card_type = getCardType(card.number);
					}
					if( response.last_four ){
						res.lastfour = response.last_four;
					} else {
						res.lastfour = card.number.substr(-4);
					}
				} else {
					res.id = response.data.id;
					res.uri = response.data.uri;
					res.card_type = response.data.card_type;
					res.lastfour = response.data.last_four;
				}

				res.month = card.expiration_month;
				res.year = card.expiration_year;
				break;

			case 400:
				var description = 'Missing card information';
				if( response.errors && response.errors[0] && response.errors[0].description ){
					if( response.errors[0].description.indexOf( '[number]' ) ){
						description = 'Not a valid credit card number';
					}
				}

				res.error = description;

				break;

			case 402:
				res.error = 'Unable to authorize card';
				break;

			case 404:
				res.error = 'Unexpected payment error';
				break;

			case 409:
				res.error = 'Unable to validate credit card';
				break;

			case 500:
				res.error = 'Error processing payment';
				break;

			// a lack of any response from the ios sdk
			case 999:
				res.error = 'Unable to reach payment server';
				break;

			// a response from the ios sdk that was both ilformated and didnt not validate
			case 666:
				res.error = 'Unable to validate your card';
				break;

			// who knows wtf this is
			default:
				console.debug('BALANCED ERROR', card, response);
				res.error = 'Unable to validate your card at this time';
				break;
		}
		completed(res);
	};

	balanced.card.create(card, handleResponse);
};
<|endoftext|>


<commit_before>
describe("Crude", function() {
	var api;

	beforeEach(function() {
		api = Crude.api('http://example.com', 'js', function(url, method, data) {
			return {url: url, method: method, data: data};
		});
	});

	describe('request', function() {
		it('should use the config passed in the Crude.api function correctly', function() {
			var data = {},
				result = api.request('test', 'put', data);

			expect(result.url).toEqual('http://example.com/test.js');
			expect(result.method).toEqual('put');
			expect(result.data).toBe(data);
		});

		it('should work with two arguments, using "get" as the default method', function() {
			var data = {},
				result = api.request('test', data);

			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('should evaluate each {prop} in the url with corresponding property from the data, also removing the prop from the latter', function() {
			var data = {
				foo: 1,
				bar: 2,
				baz: 3
			};

			var result = api.request('test/{foo}/bla/{baz}', data);

			expect(result.url).toEqual('http://example.com/test/1/bla/3.js');
			expect(result.data).toEqual({bar: 2});
		});
	});

	describe('resources', function() {
		var data = {foo: 'bar'};

		beforeEach(function() {
			api.resources('post');
		});

		it('should create a correct pluralized property in the api from resource name', function() {
			expect(api.posts).toBeDefined();

			api.resources('kitty');
			expect(api.kitties).toBeDefined();

			api.resources('wolf');
			expect(api.wolves).toBeDefined();

			api.resources('badass');
			expect(api.badasses).toBeDefined();

			api.resources('child');
			expect(api.children).toBeDefined();
		});

		it('should have get() working correctly', function() {
			var result = api.posts.get(data);

			expect(result.url).toEqual('http://example.com/posts.js');
			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('should have get(id) working correctly', function() {
			var result = api.posts.get(1, data);

			expect(result.url).toEqual('http://example.com/posts/1.js');
			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('should have create(props) working correctly', function() {
			var props = {prop: 5},
				result = api.posts.create(props, data);

			expect(result.url).toEqual('http://example.com/posts.js');
			expect(result.method).toEqual('post');
			expect(result.data).toEqual({
				'post[prop]': 5,
				foo: 'bar'
			});
		});

		it('should have update(id, props) working correctly', function() {
			var props = {prop: 5},
				result = api.posts.update(1, props, data);

			expect(result.url).toEqual('http://example.com/posts/1.js');
			expect(result.method).toEqual('put');
			expect(result.data).toEqual({
				'post[prop]': 5,
				foo: 'bar'
			});
		});

		it('should have del(id) working correctly', function() {
			var result = api.posts.del(1, data);

			expect(result.url).toEqual('http://example.com/posts/1.js');
			expect(result.method).toEqual('delete');
			expect(result.data).toBe(data);
		});

		it('memberAction(name, opts) should create corresponding method properly', function() {
			api.posts.memberAction('custom');

			var result = api.posts.custom(1, data);

			expect(result.url).toEqual('http://example.com/posts/1/custom.js');
			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('memberAction options should work properly', function() {
			function argsToData(ids) {
				return {ids: ids.join(',')};
			}

			api.posts.memberAction('custom', {
				method: 'put',
				path: 'foo/bar',
				argsToData: argsToData
			});

			var result = api.posts.custom(1, [1, 2, 3]);

			expect(result.url).toEqual('http://example.com/posts/1/foo/bar.js');
			expect(result.method).toEqual('put');
			expect(result.data).toEqual({ids: '1,2,3'});
		});

		it('collectionAction(name, opts) should create corresponding method properly', function() {
			api.posts.collectionAction('custom');

			var result = api.posts.custom(data);

			expect(result.url).toEqual('http://example.com/posts/custom.js');
			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('collectionAction options should work properly', function() {
			function argsToData(ids) {
				return {ids: ids.join(',')};
			}

			api.posts.collectionAction('custom', {
				method: 'put',
				path: 'foo/bar',
				argsToData: argsToData
			});

			var result = api.posts.custom([1, 2, 3]);

			expect(result.url).toEqual('http://example.com/posts/foo/bar.js');
			expect(result.method).toEqual('put');
			expect(result.data).toEqual({ids: '1,2,3'});
		});

		describe('child resources', function() {
			beforeEach(function() {
				api.resources('comment').belongTo(api.posts);
			});

			it('should create proper api.resources.in<Parent> accessor', function() {
				expect(api.comments.inPost).toBeDefined();
			});

			it('should create child resources prototype accessor through api.<parent><Children>', function() {
				var postComments = api.comments.inPost(2),
					postCommentsProto = postComments.constructor.prototype,
					resourcesConstructor = api.comments.constructor,
					resourcesProto = resourcesConstructor.prototype;

				expect(api.postComments).toBe(postCommentsProto);
				expect(postCommentsProto).not.toBe(resourcesProto);
				expect(postComments instanceof resourcesConstructor).toBeTruthy();
			});

			it('should have get() working correctly', function() {
				var result = api.comments.inPost(2).get();
				expect(result.url).toEqual('http://example.com/posts/2/comments.js');
			});

			it('should have get(id) working correctly', function() {
				var result = api.comments.inPost(2).get(1);
				expect(result.url).toEqual('http://example.com/posts/2/comments/1.js');
			});

			it('memberAction on particular nested resources through api.<parent><Children> should work correctly', function() {
				api.postComments.memberAction('foo');

				var result = api.comments.inPost(1).foo(2, data);

				expect(result.url).toEqual('http://example.com/posts/1/comments/2/foo.js');
				expect(result.method).toEqual('get');
				expect(result.data).toBe(data);
			});
		});
	});
});<commit_msg>update spec<commit_after>
describe("Crude", function() {
	var api;

	beforeEach(function() {
		api = Crude.api('http://example.com', 'js', function(url, method, data) {
			return {url: url, method: method, data: data};
		});
	});

	describe('request', function() {
		it('should use the config passed in the Crude.api function correctly', function() {
			var data = {},
				result = api.request('test', 'put', data);

			expect(result.url).toEqual('http://example.com/test.js');
			expect(result.method).toEqual('put');
			expect(result.data).toBe(data);
		});

		it('should work with two arguments, using "get" as the default method', function() {
			var data = {},
				result = api.request('test', data);

			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('should evaluate each {prop} in the url with corresponding property from the data, also removing the prop from the latter', function() {
			var data = {
				foo: 1,
				bar: 2,
				baz: 3
			};

			var result = api.request('test/{foo}/bla/{baz}', data);

			expect(result.url).toEqual('http://example.com/test/1/bla/3.js');
			expect(result.data).toEqual({bar: 2});
		});
	});

	describe('resources', function() {
		var data = {foo: 'bar'};

		beforeEach(function() {
			api.resources('post');
		});

		it('should create a correct pluralized property in the api from resource name', function() {
			expect(api.posts).toBeDefined();

			api.resources('kitty');
			expect(api.kitties).toBeDefined();

			api.resources('wolf');
			expect(api.wolves).toBeDefined();

			api.resources('badass');
			expect(api.badasses).toBeDefined();

			api.resources('child');
			expect(api.children).toBeDefined();
		});

		it('should have get() working correctly', function() {
			var result = api.posts.get(data);

			expect(result.url).toEqual('http://example.com/posts.js');
			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('should have get(id) working correctly', function() {
			var result = api.posts.get(1, data);

			expect(result.url).toEqual('http://example.com/posts/1.js');
			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('should have create(props) working correctly', function() {
			var props = {prop: 5},
				result = api.posts.create(props, data);

			expect(result.url).toEqual('http://example.com/posts.js');
			expect(result.method).toEqual('post');
			expect(result.data).toEqual({
				'post[prop]': 5,
				foo: 'bar'
			});
		});

		it('should have update(id, props) working correctly', function() {
			var props = {prop: 5},
				result = api.posts.update(1, props, data);

			expect(result.url).toEqual('http://example.com/posts/1.js');
			expect(result.method).toEqual('put');
			expect(result.data).toEqual({
				'post[prop]': 5,
				foo: 'bar'
			});
		});

		it('should have del(id) working correctly', function() {
			var result = api.posts.del(1, data);

			expect(result.url).toEqual('http://example.com/posts/1.js');
			expect(result.method).toEqual('delete');
			expect(result.data).toBe(data);
		});

		it('memberAction(name, opts) should create corresponding method properly', function() {
			api.posts.memberAction('custom');

			var result = api.posts.custom(1, data);

			expect(result.url).toEqual('http://example.com/posts/1/custom.js');
			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('memberAction options should work properly', function() {
			function argsToData(ids) {
				return {ids: ids.join(',')};
			}

			api.posts.memberAction('custom', {
				method: 'put',
				path: 'foo/bar',
				argsToData: argsToData
			});

			var result = api.posts.custom(1, [1, 2, 3]);

			expect(result.url).toEqual('http://example.com/posts/1/foo/bar.js');
			expect(result.method).toEqual('put');
			expect(result.data).toEqual({ids: '1,2,3'});
		});

		it('collectionAction(name, opts) should create corresponding method properly', function() {
			api.posts.collectionAction('custom');

			var result = api.posts.custom(data);

			expect(result.url).toEqual('http://example.com/posts/custom.js');
			expect(result.method).toEqual('get');
			expect(result.data).toBe(data);
		});

		it('collectionAction options should work properly', function() {
			function argsToData(ids) {
				return {ids: ids.join(',')};
			}

			api.posts.collectionAction('custom', {
				method: 'put',
				path: 'foo/bar',
				argsToData: argsToData
			});

			var result = api.posts.custom([1, 2, 3]);

			expect(result.url).toEqual('http://example.com/posts/foo/bar.js');
			expect(result.method).toEqual('put');
			expect(result.data).toEqual({ids: '1,2,3'});
		});

		describe('child resources', function() {
			beforeEach(function() {
				api.resources('comment').belongTo(api.posts);
			});

			it('should create proper api.resources.in<Parent> accessor', function() {
				expect(api.comments.inPost).toBeDefined();
			});

			it('should create child resources prototype accessor through api.<parent><Children>', function() {
				var postComments = api.comments.inPost(2),
					postCommentsProto = postComments.constructor.prototype,
					resourcesConstructor = api.comments.constructor,
					resourcesProto = resourcesConstructor.prototype;

				expect(api.postComments).toBe(postCommentsProto);
				expect(postCommentsProto).not.toBe(resourcesProto);
				expect(postComments instanceof resourcesConstructor).toBeTruthy();
			});

			it('should have get() working correctly', function() {
				var result = api.comments.inPost(2).get();
				expect(result.url).toEqual('http://example.com/posts/2/comments.js');
			});

			it('should have get(id) working correctly', function() {
				var result = api.comments.inPost(2).get(1);
				expect(result.url).toEqual('http://example.com/posts/2/comments/1.js');
			});

			it('memberAction on particular nested resources through api.<parent><Children> should work correctly', function() {
				api.postComments.memberAction('foo');

				var result = api.comments.inPost(1).foo(2, data);

				expect(result.url).toEqual('http://example.com/posts/1/comments/2/foo.js');
				expect(result.method).toEqual('get');
				expect(result.data).toBe(data);
			});

			it('api-wide memberAction on nested resources through api.nestedResources should work correctly', function() {
				api.nestedResources.memberAction('bar');

				var result = api.comments.inPost(1).bar(2, data);

				expect(result.url).toEqual('http://example.com/posts/1/comments/2/bar.js');
				expect(result.method).toEqual('get');
				expect(result.data).toBe(data);
			});
		});
	});
});<|endoftext|>


<commit_before>console.log("hi from the game.js!!")
<commit_msg>load Game object<commit_after>;(function() {
  var Game = function(canvasId) {
    var canvas = document.getElementById(canvasId);
    var screen = canvas.getContext('2d');
    var gameSize = {
      x: canvas.width,
      y: canvas.height
    };

    console.log("game loaded OK");

  };

  Game.prototype = {

  };

  window.onload = function() {
    new Game('screen');

  };

})();
<|endoftext|>


<commit_before>/**
 * znResize jQuery plugin
 *
 * @author  Zion Ng <zion@intzone.com>
 * @link    https://github.com/zionsg/zn-jquery/tree/master/znResize for canonical source repository
 * @version 1.1.0, 2013-06-26
 */

(function ($) {

    /**
     * Resize image(s) to fit parent container
     *
     * @see    $.fn.znResize.defaults for available options
     * @return DOMElement
     */
    $.fn.znResize = function (options) {
        var config = $.extend({}, $.fn.znResize.defaults, options), // merge defaults with user options
            strategies = $.fn.znResize.strategies,
            strategy = config.strategy;

        // Ensure strategy is a valid callback
        if ('string' === $.type(strategy) && strategy in $.fn.znResize.strategies) {
            strategy = $.fn.znResize.strategies[strategy];
        }
        if (!strategy || $.type(strategy) !== 'function') {
            return this;
        }

        this.each(function () {
            $(this).parent().css('overflow', 'hidden');
            strategy(this, config);
        });

        return this;
    };

    /**
     * Plugin defaults – added as a property on the plugin function
     *
     * @param string|callback strategy Default = 'crop'. Strategy for fitting image in container
     *                                 Either an existing key in $.fn.znResize.strategies or
     *                                 a user callback with the same method signature
     * @param bool center Default = true. Flag to horizontally align image in the center of parent container
     * @param bool middle Default = true. Flag to vertically align image in the middle of parent container
     */
    $.fn.znResize.defaults = {
        strategy: 'crop',
        center: true,
        middle: true
    };

    /**
     * Strategy callbacks for fitting image in container - added as a property on the plugin function
     *
     * Method signature for callback is as follows:
     * @param  DOMElement element Image element
     * @param  array      config  Merged config options
     * @return void
     */
    $.fn.znResize.strategies = {
        'crop' : function (element, config) {
            if (getNaturalWidth(element) >= getNaturalHeight(element)) {
                $(element).css('height', '100%').css('width', null);
            } else {
                $(element).css('width', '100%').css('height', null);
            }
        },

        'fit' : function (element, config) {
            var $element = $(element),
                $parent = $element.parent();

            if (getNaturalWidth(element) >= getNaturalHeight(element)) {
                $element.css('width', '100%').css('height', null);
            } else {
                $element.css('height', '100%').css('width', null);
            }

            if (config.center) {
                // computing width difference does not work if ancestors have text-align set, hence auto
                $parent.css('text-align', 'center');
                $element.css('margin-left', 'auto');
            }
            if (config.middle) {
                // 'auto' for margin does not work here
                $parent.css('vertical-align', 'middle');
                $element.css('margin-top', ($parent.height() - $element.height()) / 2);
            }
        }
    };

    /**
     * Get natural width of image element - only works if image has completed loading
     *
     * @param  DOMElement element Image element
     * @return int|float
     */
    function getNaturalWidth(element)
    {
        return element.naturalWidth || $(element).css('width', 'auto').width(); // latter to support IE8 and below
    }

    /**
     * Get natural height of image element - only works if image has completed loading
     *
     * @param  DOMElement element Image element
     * @return int|float
     */
    function getNaturalHeight(element)
    {
        return element.naturalHeight || $(element).css('height', 'auto').height(); // latter to support IE8 and below
    }

}(jQuery));
<commit_msg>Add 'defaults' & 'strategies' properties; Add 'fit' strategy.<commit_after>/**
 * znResize jQuery plugin
 *
 * @author  Zion Ng <zion@intzone.com>
 * @link    https://github.com/zionsg/zn-jquery/tree/master/znResize for canonical source repository
 * @version 1.1.0, 2013-06-26
 */

(function ($) {

    /**
     * Resize image(s) to fit parent container
     *
     * @see    $.fn.znResize.defaults for available options
     * @return DOMElement
     */
    $.fn.znResize = function (options) {
        var config = $.extend({}, $.fn.znResize.defaults, options), // merge defaults with user options
            strategies = $.fn.znResize.strategies,
            strategy = config.strategy;

        // Ensure strategy is a valid callback
        if ('string' === $.type(strategy) && strategy in $.fn.znResize.strategies) {
            strategy = $.fn.znResize.strategies[strategy];
        }
        if (!strategy || $.type(strategy) !== 'function') {
            return this;
        }

        this.each(function () {
            $(this).parent().css('overflow', 'hidden');
            strategy(this, config);
        });

        return this;
    };

    /**
     * Plugin defaults – added as a property on the plugin function
     *
     * @param string|callback strategy Default = 'crop'. Strategy for fitting image in container
     *                                 Either an existing key in $.fn.znResize.strategies or
     *                                 a user callback with the same method signature
     * @param bool center Default = true. Flag to horizontally align image in the center of parent container
     * @param bool middle Default = true. Flag to vertically align image in the middle of parent container
     */
    $.fn.znResize.defaults = {
        strategy: 'crop',
        center: true,
        middle: true
    };

    /**
     * Strategy callbacks for fitting image in container - added as a property on the plugin function
     *
     * Method signature for callback is as follows:
     * @param  DOMElement element Image element
     * @param  array      config  Merged config options
     * @return void
     */
    $.fn.znResize.strategies = {
        'crop' : function (element, config) {
            if (getNaturalWidth(element) >= getNaturalHeight(element)) {
                $(element).css('height', '100%').css('width', null);
            } else {
                $(element).css('width', '100%').css('height', null);
            }
        },

        'fit' : function (element, config) {
            var $element = $(element),
                $parent = $element.parent();

            if (getNaturalWidth(element) >= getNaturalHeight(element)) {
                $element.css('width', '100%').css('height', null);
            } else {
                $element.css('height', '100%').css('width', null);
            }

            if (config.center) {
                // computing width difference does not work if ancestors have text-align set, hence auto
                $parent.css('text-align', 'center');
                $element.css('margin-left', 'auto');
            }
            if (config.middle) {
                // 'auto' for margin does not work here, hence using height difference
                $parent.css('vertical-align', 'middle');
                $element.css('margin-top', ($parent.height() - $element.height()) / 2);
            }
        }
    };

    /**
     * Get natural width of image element - only works if image has completed loading
     *
     * @param  DOMElement element Image element
     * @return int|float
     */
    function getNaturalWidth(element)
    {
        return element.naturalWidth || $(element).css('width', 'auto').width(); // latter to support IE8 and below
    }

    /**
     * Get natural height of image element - only works if image has completed loading
     *
     * @param  DOMElement element Image element
     * @return int|float
     */
    function getNaturalHeight(element)
    {
        return element.naturalHeight || $(element).css('height', 'auto').height(); // latter to support IE8 and below
    }

}(jQuery));
<|endoftext|>


<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

var tideline = window.tideline;
var watson = tideline.watson;
var _ = tideline.lib._;
var TidelineData = tideline.TidelineData;
var SegmentUtil = tideline.data.SegmentUtil;

var log = tideline.lib.bows('Preprocess');

function alwaysTrue() {
  return true;
}

function notZero(e) {
  return e.value !== 0;
}

/**
 * This converts suspend start and end events into basal-rate-segments for the visualization
 *
 * @param data Array of data, assumed to be only deviceMeta events.
 * @returns {Array} modified array of data to have basal-rate-segments for suspend start and end events.
 */
function processSuspends(data) {
  data = _.sortBy(data, 'deviceTime');

  var retVal = [];
  var suspends = {};

  for (var i = 0; i < data.length; ++i) {
    if (data[i].subType === 'status') {
      switch (data[i].status) {
        case 'suspended':
          suspends[data[i].id] = data[i];
          break;
        case 'resume':
          if (data[i].joinKey == null) {
            retVal.push(data[i]);
          } else {
            var suspended = suspends[data[i].joinKey];

            if (suspended == null) {
              retVal.push(data[i]);
            } else {
              retVal.push(
                _.assign({}, suspended,
                {
                  id: suspended.id + '_' + data[i].id,
                  type: 'basal-rate-segment',
                  start: suspended.deviceTime,
                  end: data[i].deviceTime,
                  deliveryType: 'suspend',
                  value: 0
                }
                )
              );
              delete suspends[data[i].joinKey];
            }
          }
          break;
        default:
          retVal.push(data[i]);
      }
    } else {
      retVal.push(data[i]);
    }
  }

  return retVal.concat(Object.keys(suspends).map(function(key){ return suspends[key]; }));
}

var TYPES_TO_INCLUDE = {
  // basals with value 0 don't get excluded because they are legitimate targets for visualization
  'basal-rate-segment': function(e){ return e.start !== e.end; },
  bolus: notZero,
  carbs: notZero,
  cbg: notZero,
  deviceMeta: alwaysTrue,
  message: notZero,
  smbg: notZero,
  settings: notZero
};

var Preprocess = {

  REQUIRED_TYPES: ['basal-rate-segment', 'bolus', 'carbs', 'cbg', 'message', 'smbg', 'settings'],

  OPTIONAL_TYPES: [],

  MMOL_STRING: 'mmol/L',

  MGDL_STRING: 'mg/dL',

  MMOL_TO_MGDL: 18,

  mungeBasals: function(data) {
    var segments = new SegmentUtil(_.sortBy(_.where(data, {'type': 'basal-rate-segment'}), 'deviceTime'));
    data = _.reject(data, function(d) {
      return d.type === 'basal-rate-segment';
    });
    data = data.concat(segments.actual.concat(segments.getUndelivered('scheduled')));
    return data;
  },

  editBoluses: function(data) {
    // two adjustments to boluses here:
    // changed `extended` to false when extendedDelivery = 0
    // (these are instances where someone changed their mind about a combo bolus, basically)
    // ~and~
    // when there is a joinKey to a wizard event from which we can obtain
    // the recommendation for a bolus, extract it to populate the `recommended` field
    var wizards = _.indexBy(data, function(d) {
      if (d.type === 'wizard') {
        return d.joinKey;
      }
    });
    return _.map(data, function(d) {
      if (d.type === 'bolus' && d.joinKey != null) {
        var joined = wizards[d.joinKey];
        if (joined && joined.payload.estimate != null) {
          d.recommended = joined.payload.estimate;
        }
        return d;
      }
      if (d.extended && d.extendedDelivery === 0) {
        d.extended = false;
        return d;
      }
      else {
        return d;
      }
    });
  },

  filterData: function(data) {
    // filter out types we aren't using for visualization
    //  ~and~
    // because of how the Tidepool back end parses some data sources
    // we're creating things like carb events with values of 0, which
    // we don't want to visualize, so...
    // this function also removes all data with value 0 except for basals, since
    // we do want to visualize basals (e.g., temps) with value 0.0

    var counts = {};

    function incrementCount(count, type) {
      if (counts[count] == null) {
        counts[count] = {};
      }

      if (counts[count][type] == null) {
        counts[count][type] = 0;
      }

      ++counts[count][type];
    }

    var nonZeroData = _.filter(data, function(d) {
      var includeFn = TYPES_TO_INCLUDE[d.type];
      if (includeFn == null) {
        incrementCount('excluded', d.type);
        return false;
      }

      var retVal = includeFn(d);
      incrementCount(retVal ? 'included' : 'excluded', d.type);
      return retVal;
    });

    log('Excluded:', counts.excluded || 0);
    log('# of data points', nonZeroData.length);
    log('Data types:', counts.included);

    return nonZeroData;
  },

  processDeviceMeta: function(data) {
    var other = [];
    var deviceMeta = [];

    for (var i = 0; i < data.length; ++i) {
      if (data[i].type === 'deviceMeta') {
        deviceMeta.push(data[i]);
      } else {
        other.push(data[i]);
      }
    }

    return other.concat(processSuspends(deviceMeta));
  },

  runWatson: function(data) {
    data = watson.normalizeAll(data);
    // Ensure the data is properly sorted
    data = _.sortBy(data, function(d) {
      // ISO8601 format lexicographically sorts according to timestamp
      return d.normalTime;
    });
    return data;
  },

  checkRequired: function(tidelineData) {
    _.forEach(this.REQUIRED_TYPES, function(type) {
      if (!tidelineData.grouped[type]) {
        log('No', type, 'data! Replaced with empty array.');
        tidelineData.grouped[type] = [];
      }
    });

    return tidelineData;
  },

  translateMmol: function(data) {
    return _.map(data, function(d) {
      if (d.units === this.MMOL_STRING) {
        d.units = this.MGDL_STRING;
        d.value = parseInt(Math.round(d.value * this.MMOL_TO_MGDL, 10));
      }
      return d;
    }, this);
  },

  basalSchedulesToArray: function(basalSchedules) {
    var schedules = [];
    for(var key in basalSchedules) {
      schedules.push({
        'name': key,
        'value': basalSchedules[key]
      });
    }
    return schedules;
  },

  sortBasalSchedules: function(data) {
    return _.map(data, function(d) {
      var schedules;
      if (d.type === 'settings') {
        schedules = this.basalSchedulesToArray(d.basalSchedules);
        if (d.source === 'carelink') {
          for (var i = 0; i < schedules.length; i++) {
            if (schedules[i].name === 'standard') {
              var standard = schedules[i];
              var index = schedules.indexOf(standard);
              schedules.splice(index, 1);
              schedules.unshift(standard);
              break;
            }
          }
        }
        d.basalSchedules = schedules;
        return d;
      }
      else {
        return d;
      }
    }, this);
  },

  processData: function(data) {
    if (!(data && data.length)) {
      log('Unexpected data input, defaulting to empty array.');
      data = [];
    }

    data = this.editBoluses(data);
    data = this.filterData(data);
    data = this.processDeviceMeta(data);
    data = this.mungeBasals(data);
    data = this.runWatson(data);
    data = this.translateMmol(data);
    data = this.sortBasalSchedules(data);

    var tidelineData = this.checkRequired(new TidelineData(data));

    return tidelineData;
  }
};

module.exports = Preprocess;
<commit_msg>Standardize on past tense<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

var tideline = window.tideline;
var watson = tideline.watson;
var _ = tideline.lib._;
var TidelineData = tideline.TidelineData;
var SegmentUtil = tideline.data.SegmentUtil;

var log = tideline.lib.bows('Preprocess');

function alwaysTrue() {
  return true;
}

function notZero(e) {
  return e.value !== 0;
}

/**
 * This converts suspend start and end events into basal-rate-segments for the visualization
 *
 * @param data Array of data, assumed to be only deviceMeta events.
 * @returns {Array} modified array of data to have basal-rate-segments for suspend start and end events.
 */
function processSuspends(data) {
  data = _.sortBy(data, 'deviceTime');

  var retVal = [];
  var suspends = {};

  for (var i = 0; i < data.length; ++i) {
    if (data[i].subType === 'status') {
      switch (data[i].status) {
        case 'suspended':
          suspends[data[i].id] = data[i];
          break;
        case 'resumed':
        case 'resume': // 2014-05-06: Non past-tense should be removed.  If this still exists in June, please remove
          if (data[i].joinKey == null) {
            retVal.push(data[i]);
          } else {
            var suspended = suspends[data[i].joinKey];

            if (suspended == null) {
              retVal.push(data[i]);
            } else {
              retVal.push(
                _.assign({}, suspended,
                {
                  id: suspended.id + '_' + data[i].id,
                  type: 'basal-rate-segment',
                  start: suspended.deviceTime,
                  end: data[i].deviceTime,
                  deliveryType: 'suspend',
                  value: 0
                }
                )
              );
              delete suspends[data[i].joinKey];
            }
          }
          break;
        default:
          retVal.push(data[i]);
      }
    } else {
      retVal.push(data[i]);
    }
  }

  return retVal.concat(Object.keys(suspends).map(function(key){ return suspends[key]; }));
}

var TYPES_TO_INCLUDE = {
  // basals with value 0 don't get excluded because they are legitimate targets for visualization
  'basal-rate-segment': function(e){ return e.start !== e.end; },
  bolus: notZero,
  carbs: notZero,
  cbg: notZero,
  deviceMeta: alwaysTrue,
  message: notZero,
  smbg: notZero,
  settings: notZero
};

var Preprocess = {

  REQUIRED_TYPES: ['basal-rate-segment', 'bolus', 'carbs', 'cbg', 'message', 'smbg', 'settings'],

  OPTIONAL_TYPES: [],

  MMOL_STRING: 'mmol/L',

  MGDL_STRING: 'mg/dL',

  MMOL_TO_MGDL: 18,

  mungeBasals: function(data) {
    var segments = new SegmentUtil(_.sortBy(_.where(data, {'type': 'basal-rate-segment'}), 'deviceTime'));
    data = _.reject(data, function(d) {
      return d.type === 'basal-rate-segment';
    });
    data = data.concat(segments.actual.concat(segments.getUndelivered('scheduled')));
    return data;
  },

  editBoluses: function(data) {
    // two adjustments to boluses here:
    // changed `extended` to false when extendedDelivery = 0
    // (these are instances where someone changed their mind about a combo bolus, basically)
    // ~and~
    // when there is a joinKey to a wizard event from which we can obtain
    // the recommendation for a bolus, extract it to populate the `recommended` field
    var wizards = _.indexBy(data, function(d) {
      if (d.type === 'wizard') {
        return d.joinKey;
      }
    });
    return _.map(data, function(d) {
      if (d.type === 'bolus' && d.joinKey != null) {
        var joined = wizards[d.joinKey];
        if (joined && joined.payload.estimate != null) {
          d.recommended = joined.payload.estimate;
        }
        return d;
      }
      if (d.extended && d.extendedDelivery === 0) {
        d.extended = false;
        return d;
      }
      else {
        return d;
      }
    });
  },

  filterData: function(data) {
    // filter out types we aren't using for visualization
    //  ~and~
    // because of how the Tidepool back end parses some data sources
    // we're creating things like carb events with values of 0, which
    // we don't want to visualize, so...
    // this function also removes all data with value 0 except for basals, since
    // we do want to visualize basals (e.g., temps) with value 0.0

    var counts = {};

    function incrementCount(count, type) {
      if (counts[count] == null) {
        counts[count] = {};
      }

      if (counts[count][type] == null) {
        counts[count][type] = 0;
      }

      ++counts[count][type];
    }

    var nonZeroData = _.filter(data, function(d) {
      var includeFn = TYPES_TO_INCLUDE[d.type];
      if (includeFn == null) {
        incrementCount('excluded', d.type);
        return false;
      }

      var retVal = includeFn(d);
      incrementCount(retVal ? 'included' : 'excluded', d.type);
      return retVal;
    });

    log('Excluded:', counts.excluded || 0);
    log('# of data points', nonZeroData.length);
    log('Data types:', counts.included);

    return nonZeroData;
  },

  processDeviceMeta: function(data) {
    var other = [];
    var deviceMeta = [];

    for (var i = 0; i < data.length; ++i) {
      if (data[i].type === 'deviceMeta') {
        deviceMeta.push(data[i]);
      } else {
        other.push(data[i]);
      }
    }

    return other.concat(processSuspends(deviceMeta));
  },

  runWatson: function(data) {
    data = watson.normalizeAll(data);
    // Ensure the data is properly sorted
    data = _.sortBy(data, function(d) {
      // ISO8601 format lexicographically sorts according to timestamp
      return d.normalTime;
    });
    return data;
  },

  checkRequired: function(tidelineData) {
    _.forEach(this.REQUIRED_TYPES, function(type) {
      if (!tidelineData.grouped[type]) {
        log('No', type, 'data! Replaced with empty array.');
        tidelineData.grouped[type] = [];
      }
    });

    return tidelineData;
  },

  translateMmol: function(data) {
    return _.map(data, function(d) {
      if (d.units === this.MMOL_STRING) {
        d.units = this.MGDL_STRING;
        d.value = parseInt(Math.round(d.value * this.MMOL_TO_MGDL, 10));
      }
      return d;
    }, this);
  },

  basalSchedulesToArray: function(basalSchedules) {
    var schedules = [];
    for(var key in basalSchedules) {
      schedules.push({
        'name': key,
        'value': basalSchedules[key]
      });
    }
    return schedules;
  },

  sortBasalSchedules: function(data) {
    return _.map(data, function(d) {
      var schedules;
      if (d.type === 'settings') {
        schedules = this.basalSchedulesToArray(d.basalSchedules);
        if (d.source === 'carelink') {
          for (var i = 0; i < schedules.length; i++) {
            if (schedules[i].name === 'standard') {
              var standard = schedules[i];
              var index = schedules.indexOf(standard);
              schedules.splice(index, 1);
              schedules.unshift(standard);
              break;
            }
          }
        }
        d.basalSchedules = schedules;
        return d;
      }
      else {
        return d;
      }
    }, this);
  },

  processData: function(data) {
    if (!(data && data.length)) {
      log('Unexpected data input, defaulting to empty array.');
      data = [];
    }

    data = this.editBoluses(data);
    data = this.filterData(data);
    data = this.processDeviceMeta(data);
    data = this.mungeBasals(data);
    data = this.runWatson(data);
    data = this.translateMmol(data);
    data = this.sortBasalSchedules(data);

    var tidelineData = this.checkRequired(new TidelineData(data));

    return tidelineData;
  }
};

module.exports = Preprocess;
<|endoftext|>