<commit_before>'use strict';

var _ = require('lodash');
var BlockHeader = require('./blockheader');
var BufferUtil = require('../util/buffer');
var BufferReader = require('../encoding/bufferreader');
var BufferWriter = require('../encoding/bufferwriter');
var Hash = require('../crypto/hash');
var JSUtil = require('../util/js');
var Transaction = require('../transaction');
var errors = require('../errors');
var $ = require('../util/preconditions');

/**
 * Instantiate a MerkleBlock from a Buffer, JSON object, or Object with
 * the properties of the Block
 *
 * @param {*} - A Buffer, JSON string, or Object representing a MerkleBlock
 * @returns {MerkleBlock}
 * @constructor
 */
function MerkleBlock(arg) {
  /* jshint maxstatements: 18 */

  if (!(this instanceof MerkleBlock)) {
    return new MerkleBlock(arg);
  }

  var info = {};
  if (BufferUtil.isBuffer(arg)) {
    info = MerkleBlock._fromBufferReader(BufferReader(arg));
  } else if (_.isObject(arg)) {
    var header;
    if(arg.header instanceof BlockHeader) {
      header = arg.header;
    } else {
      header = BlockHeader.fromObject(arg.header);
    }
    info = {
      /**
       * @name MerkleBlock#header
       * @type {BlockHeader}
       */
      header: header,
      /**
       * @name MerkleBlock#numTransactions
       * @type {Number}
       */
      numTransactions: arg.numTransactions,
      /**
       * @name MerkleBlock#hashes
       * @type {String[]}
       */
      hashes: arg.hashes,
      /**
       * @name MerkleBlock#flags
       * @type {Number[]}
       */
      flags: arg.flags
    };
  } else {
    throw new TypeError('Unrecognized argument for MerkleBlock');
  }
  _.extend(this,info);
  this._flagBitsUsed = 0;
  this._hashesUsed = 0;

  return this;
}

/**
 * @param {Buffer} - MerkleBlock data in a Buffer object
 * @returns {MerkleBlock} - A MerkleBlock object
 */
MerkleBlock.fromBuffer = function fromBuffer(buf) {
  return MerkleBlock.fromBufferReader(BufferReader(buf));
};

/**
 * @param {BufferReader} - MerkleBlock data in a BufferReader object
 * @returns {MerkleBlock} - A MerkleBlock object
 */
MerkleBlock.fromBufferReader = function fromBufferReader(br) {
  return new MerkleBlock(MerkleBlock._fromBufferReader(br));
};

/**
 * @returns {Buffer} - A buffer of the block
 */
MerkleBlock.prototype.toBuffer = function toBuffer() {
  return this.toBufferWriter().concat();
};

/**
 * @param {BufferWriter} - An existing instance of BufferWriter
 * @returns {BufferWriter} - An instance of BufferWriter representation of the MerkleBlock
 */
MerkleBlock.prototype.toBufferWriter = function toBufferWriter(bw) {
  if (!bw) {
    bw = new BufferWriter();
  }
  bw.write(this.header.toBuffer());
  bw.writeUInt32LE(this.numTransactions);
  bw.writeVarintNum(this.hashes.length);
  for (var i = 0; i < this.hashes.length; i++) {
    bw.write(new Buffer(this.hashes[i], 'hex'));
  }
  bw.writeVarintNum(this.flags.length);
  for (i = 0; i < this.flags.length; i++) {
    bw.writeUInt8(this.flags[i]);
  }
  return bw;
};

/**
 * @returns {Object} - A plain object with the MerkleBlock properties
 */
MerkleBlock.prototype.toObject = MerkleBlock.prototype.toJSON = function toObject() {
  return {
    header: this.header.toObject(),
    numTransactions: this.numTransactions,
    hashes: this.hashes,
    flags: this.flags
  };
};

/**
 * Verify that the MerkleBlock is valid
 * @returns {Boolean} - True/False whether this MerkleBlock is Valid
 */
MerkleBlock.prototype.validMerkleTree = function validMerkleTree() {
  $.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array');
  $.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array');

  // Can't have more hashes than numTransactions
  if(this.hashes.length > this.numTransactions) {
    return false;
  }

  // Can't have more flag bits than num hashes
  if(this.flags.length * 8 < this.hashes.length) {
    return false;
  }

  var height = this._calcTreeHeight();
  var opts = { hashesUsed: 0, flagBitsUsed: 0 };
  var root = this._traverseMerkleTree(height, 0, opts);
  if(opts.hashesUsed !== this.hashes.length) {
    return false;
  }
  return BufferUtil.equals(root, this.header.merkleRoot);
};

/**
 * Return a list of all the txs hash that match the filter
 * @returns {Array} - txs hash that match the filter
 */
MerkleBlock.prototype.filterdTxsHash = function validMerkleTree() {
  $.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array');
  $.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array');

  // Can't have more hashes than numTransactions
  if(this.hashes.length > this.numTransactions) {
    throw new errors.MerkleBlock.InvalidMerkleTree();
  }

  // Can't have more flag bits than num hashes
  if(this.flags.length * 8 < this.hashes.length) {
    throw new errors.MerkleBlock.InvalidMerkleTree();
  }

  var height = this._calcTreeHeight();
  var opts = { hashesUsed: 0, flagBitsUsed: 0 };
  var txs = this._traverseMerkleTree(height, 0, opts, true);
  if(opts.hashesUsed !== this.hashes.length) {
    throw new errors.MerkleBlock.InvalidMerkleTree();
  }
  return txs;
};

/**
 * Traverse a the tree in this MerkleBlock, validating it along the way
 * Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract()
 * @param {Number} - depth - Current height
 * @param {Number} - pos - Current position in the tree
 * @param {Object} - opts - Object with values that need to be mutated throughout the traversal
 * @param {Boolean} - checkForTxs - if true return opts.txs else return the Merkle Hash
 * @param {Number} - opts.flagBitsUsed - Number of flag bits used, should start at 0
 * @param {Number} - opts.hashesUsed - Number of hashes used, should start at 0
 * @param {Array} - opts.txs - Will finish populated by transactions found during traversal that match the filter
 * @returns {Buffer|null} - Buffer containing the Merkle Hash for that height
 * @returns {Array} - transactions found during traversal that match the filter
 * @private
 */
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos, opts, checkForTxs) {
  /* jshint maxcomplexity:  12*/
  /* jshint maxstatements: 20 */

  opts = opts || {};
  opts.txs = opts.txs || [];
  opts.flagBitsUsed = opts.flagBitsUsed || 0;
  opts.hashesUsed = opts.hashesUsed || 0;
  var checkForTxs = checkForTxs || false;

  if(opts.flagBitsUsed > this.flags.length * 8) {
    return null;
  }
  var isParentOfMatch = (this.flags[opts.flagBitsUsed >> 3] >>> (opts.flagBitsUsed++ & 7)) & 1;
  if(depth === 0 || !isParentOfMatch) {
    if(opts.hashesUsed >= this.hashes.length) {
      return null;
    }
    var hash = this.hashes[opts.hashesUsed++];
    if(depth === 0 && isParentOfMatch) {
      opts.txs.push(hash);
    }
    return new Buffer(hash, 'hex');
  } else {
    var left = this._traverseMerkleTree(depth-1, pos*2, opts);
    var right = left;
    if(pos*2+1 < this._calcTreeWidth(depth-1)) {
      right = this._traverseMerkleTree(depth-1, pos*2+1, opts);
    }
    if (checkForTxs){
      return opts.txs;
    } else {
      return Hash.sha256sha256(new Buffer.concat([left, right]));
    };
  }
};

/** Calculates the width of a merkle tree at a given height.
 *  Modeled after Bitcoin Core merkleblock.h CalcTreeWidth()
 * @param {Number} - Height at which we want the tree width
 * @returns {Number} - Width of the tree at a given height
 * @private
 */
MerkleBlock.prototype._calcTreeWidth = function calcTreeWidth(height) {
  return (this.numTransactions + (1 << height) - 1) >> height;
};

/** Calculates the height of the merkle tree in this MerkleBlock
 * @param {Number} - Height at which we want the tree width
 * @returns {Number} - Height of the merkle tree in this MerkleBlock
 * @private
 */
MerkleBlock.prototype._calcTreeHeight = function calcTreeHeight() {
  var height = 0;
  while (this._calcTreeWidth(height) > 1) {
    height++;
  }
  return height;
};

/**
 * @param {Transaction|String} - Transaction or Transaction ID Hash
 * @returns {Boolean} - return true/false if this MerkleBlock has the TX or not
 * @private
 */
MerkleBlock.prototype.hasTransaction = function hasTransaction(tx) {
  $.checkArgument(!_.isUndefined(tx), 'tx cannot be undefined');
  $.checkArgument(tx instanceof Transaction || typeof tx === 'string',
      'Invalid tx given, tx must be a "string" or "Transaction"');

  var hash = tx;
  if(tx instanceof Transaction) {
    // We need to reverse the id hash for the lookup
    hash = BufferUtil.reverse(new Buffer(tx.id, 'hex')).toString('hex');
  }

  var txs = [];
  var height = this._calcTreeHeight();
  this._traverseMerkleTree(height, 0, { txs: txs });
  return txs.indexOf(hash) !== -1;
};

/**
 * @param {Buffer} - MerkleBlock data
 * @returns {Object} - An Object representing merkleblock data
 * @private
 */
MerkleBlock._fromBufferReader = function _fromBufferReader(br) {
  $.checkState(!br.finished(), 'No merkleblock data received');
  var info = {};
  info.header = BlockHeader.fromBufferReader(br);
  info.numTransactions = br.readUInt32LE();
  var numHashes = br.readVarintNum();
  info.hashes = [];
  for (var i = 0; i < numHashes; i++) {
    info.hashes.push(br.read(32).toString('hex'));
  }
  var numFlags = br.readVarintNum();
  info.flags = [];
  for (i = 0; i < numFlags; i++) {
    info.flags.push(br.readUInt8());
  }
  return info;
};

/**
 * @param {Object} - A plain JavaScript object
 * @returns {Block} - An instance of block
 */
MerkleBlock.fromObject = function fromObject(obj) {
  return new MerkleBlock(obj);
};

module.exports = MerkleBlock;
<commit_msg>fixed filteredTxsHash If there is only one hash the filter do not match any txs in the block and should return a void aray<commit_after>'use strict';

var _ = require('lodash');
var BlockHeader = require('./blockheader');
var BufferUtil = require('../util/buffer');
var BufferReader = require('../encoding/bufferreader');
var BufferWriter = require('../encoding/bufferwriter');
var Hash = require('../crypto/hash');
var JSUtil = require('../util/js');
var Transaction = require('../transaction');
var errors = require('../errors');
var $ = require('../util/preconditions');

/**
 * Instantiate a MerkleBlock from a Buffer, JSON object, or Object with
 * the properties of the Block
 *
 * @param {*} - A Buffer, JSON string, or Object representing a MerkleBlock
 * @returns {MerkleBlock}
 * @constructor
 */
function MerkleBlock(arg) {
  /* jshint maxstatements: 18 */

  if (!(this instanceof MerkleBlock)) {
    return new MerkleBlock(arg);
  }

  var info = {};
  if (BufferUtil.isBuffer(arg)) {
    info = MerkleBlock._fromBufferReader(BufferReader(arg));
  } else if (_.isObject(arg)) {
    var header;
    if(arg.header instanceof BlockHeader) {
      header = arg.header;
    } else {
      header = BlockHeader.fromObject(arg.header);
    }
    info = {
      /**
       * @name MerkleBlock#header
       * @type {BlockHeader}
       */
      header: header,
      /**
       * @name MerkleBlock#numTransactions
       * @type {Number}
       */
      numTransactions: arg.numTransactions,
      /**
       * @name MerkleBlock#hashes
       * @type {String[]}
       */
      hashes: arg.hashes,
      /**
       * @name MerkleBlock#flags
       * @type {Number[]}
       */
      flags: arg.flags
    };
  } else {
    throw new TypeError('Unrecognized argument for MerkleBlock');
  }
  _.extend(this,info);
  this._flagBitsUsed = 0;
  this._hashesUsed = 0;

  return this;
}

/**
 * @param {Buffer} - MerkleBlock data in a Buffer object
 * @returns {MerkleBlock} - A MerkleBlock object
 */
MerkleBlock.fromBuffer = function fromBuffer(buf) {
  return MerkleBlock.fromBufferReader(BufferReader(buf));
};

/**
 * @param {BufferReader} - MerkleBlock data in a BufferReader object
 * @returns {MerkleBlock} - A MerkleBlock object
 */
MerkleBlock.fromBufferReader = function fromBufferReader(br) {
  return new MerkleBlock(MerkleBlock._fromBufferReader(br));
};

/**
 * @returns {Buffer} - A buffer of the block
 */
MerkleBlock.prototype.toBuffer = function toBuffer() {
  return this.toBufferWriter().concat();
};

/**
 * @param {BufferWriter} - An existing instance of BufferWriter
 * @returns {BufferWriter} - An instance of BufferWriter representation of the MerkleBlock
 */
MerkleBlock.prototype.toBufferWriter = function toBufferWriter(bw) {
  if (!bw) {
    bw = new BufferWriter();
  }
  bw.write(this.header.toBuffer());
  bw.writeUInt32LE(this.numTransactions);
  bw.writeVarintNum(this.hashes.length);
  for (var i = 0; i < this.hashes.length; i++) {
    bw.write(new Buffer(this.hashes[i], 'hex'));
  }
  bw.writeVarintNum(this.flags.length);
  for (i = 0; i < this.flags.length; i++) {
    bw.writeUInt8(this.flags[i]);
  }
  return bw;
};

/**
 * @returns {Object} - A plain object with the MerkleBlock properties
 */
MerkleBlock.prototype.toObject = MerkleBlock.prototype.toJSON = function toObject() {
  return {
    header: this.header.toObject(),
    numTransactions: this.numTransactions,
    hashes: this.hashes,
    flags: this.flags
  };
};

/**
 * Verify that the MerkleBlock is valid
 * @returns {Boolean} - True/False whether this MerkleBlock is Valid
 */
MerkleBlock.prototype.validMerkleTree = function validMerkleTree() {
  $.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array');
  $.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array');

  // Can't have more hashes than numTransactions
  if(this.hashes.length > this.numTransactions) {
    return false;
  }

  // Can't have more flag bits than num hashes
  if(this.flags.length * 8 < this.hashes.length) {
    return false;
  }

  var height = this._calcTreeHeight();
  var opts = { hashesUsed: 0, flagBitsUsed: 0 };
  var root = this._traverseMerkleTree(height, 0, opts);
  if(opts.hashesUsed !== this.hashes.length) {
    return false;
  }
  return BufferUtil.equals(root, this.header.merkleRoot);
};

/**
 * Return a list of all the txs hash that match the filter
 * @returns {Array} - txs hash that match the filter
 */
MerkleBlock.prototype.filterdTxsHash = function filterdTxsHash() {
  $.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array');
  $.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array');

  // Can't have more hashes than numTransactions
  if(this.hashes.length > this.numTransactions) {
    throw new errors.MerkleBlock.InvalidMerkleTree();
  }

  // Can't have more flag bits than num hashes
  if(this.flags.length * 8 < this.hashes.length) {
    throw new errors.MerkleBlock.InvalidMerkleTree();
  }

  // If there is only one hash the filter do not match any txs in the block
  if(this.hashes.length === 1) {
    return [];
  };

  var height = this._calcTreeHeight();
  var opts = { hashesUsed: 0, flagBitsUsed: 0 };
  var txs = this._traverseMerkleTree(height, 0, opts, true);
  if(opts.hashesUsed !== this.hashes.length) {
    throw new errors.MerkleBlock.InvalidMerkleTree();
  }
  return txs;
};

/**
 * Traverse a the tree in this MerkleBlock, validating it along the way
 * Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract()
 * @param {Number} - depth - Current height
 * @param {Number} - pos - Current position in the tree
 * @param {Object} - opts - Object with values that need to be mutated throughout the traversal
 * @param {Boolean} - checkForTxs - if true return opts.txs else return the Merkle Hash
 * @param {Number} - opts.flagBitsUsed - Number of flag bits used, should start at 0
 * @param {Number} - opts.hashesUsed - Number of hashes used, should start at 0
 * @param {Array} - opts.txs - Will finish populated by transactions found during traversal that match the filter
 * @returns {Buffer|null} - Buffer containing the Merkle Hash for that height
 * @returns {Array} - transactions found during traversal that match the filter
 * @private
 */
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos, opts, checkForTxs) {
  /* jshint maxcomplexity:  12*/
  /* jshint maxstatements: 20 */

  opts = opts || {};
  opts.txs = opts.txs || [];
  opts.flagBitsUsed = opts.flagBitsUsed || 0;
  opts.hashesUsed = opts.hashesUsed || 0;
  var checkForTxs = checkForTxs || false;

  if(opts.flagBitsUsed > this.flags.length * 8) {
    return null;
  }
  var isParentOfMatch = (this.flags[opts.flagBitsUsed >> 3] >>> (opts.flagBitsUsed++ & 7)) & 1;
  if(depth === 0 || !isParentOfMatch) {
    if(opts.hashesUsed >= this.hashes.length) {
      return null;
    }
    var hash = this.hashes[opts.hashesUsed++];
    if(depth === 0 && isParentOfMatch) {
      opts.txs.push(hash);
    }
    return new Buffer(hash, 'hex');
  } else {
    var left = this._traverseMerkleTree(depth-1, pos*2, opts);
    var right = left;
    if(pos*2+1 < this._calcTreeWidth(depth-1)) {
      right = this._traverseMerkleTree(depth-1, pos*2+1, opts);
    }
    if (checkForTxs){
      return opts.txs;
    } else {
      return Hash.sha256sha256(new Buffer.concat([left, right]));
    };
  }
};

/** Calculates the width of a merkle tree at a given height.
 *  Modeled after Bitcoin Core merkleblock.h CalcTreeWidth()
 * @param {Number} - Height at which we want the tree width
 * @returns {Number} - Width of the tree at a given height
 * @private
 */
MerkleBlock.prototype._calcTreeWidth = function calcTreeWidth(height) {
  return (this.numTransactions + (1 << height) - 1) >> height;
};

/** Calculates the height of the merkle tree in this MerkleBlock
 * @param {Number} - Height at which we want the tree width
 * @returns {Number} - Height of the merkle tree in this MerkleBlock
 * @private
 */
MerkleBlock.prototype._calcTreeHeight = function calcTreeHeight() {
  var height = 0;
  while (this._calcTreeWidth(height) > 1) {
    height++;
  }
  return height;
};

/**
 * @param {Transaction|String} - Transaction or Transaction ID Hash
 * @returns {Boolean} - return true/false if this MerkleBlock has the TX or not
 * @private
 */
MerkleBlock.prototype.hasTransaction = function hasTransaction(tx) {
  $.checkArgument(!_.isUndefined(tx), 'tx cannot be undefined');
  $.checkArgument(tx instanceof Transaction || typeof tx === 'string',
      'Invalid tx given, tx must be a "string" or "Transaction"');

  var hash = tx;
  if(tx instanceof Transaction) {
    // We need to reverse the id hash for the lookup
    hash = BufferUtil.reverse(new Buffer(tx.id, 'hex')).toString('hex');
  }

  var txs = [];
  var height = this._calcTreeHeight();
  this._traverseMerkleTree(height, 0, { txs: txs });
  return txs.indexOf(hash) !== -1;
};

/**
 * @param {Buffer} - MerkleBlock data
 * @returns {Object} - An Object representing merkleblock data
 * @private
 */
MerkleBlock._fromBufferReader = function _fromBufferReader(br) {
  $.checkState(!br.finished(), 'No merkleblock data received');
  var info = {};
  info.header = BlockHeader.fromBufferReader(br);
  info.numTransactions = br.readUInt32LE();
  var numHashes = br.readVarintNum();
  info.hashes = [];
  for (var i = 0; i < numHashes; i++) {
    info.hashes.push(br.read(32).toString('hex'));
  }
  var numFlags = br.readVarintNum();
  info.flags = [];
  for (i = 0; i < numFlags; i++) {
    info.flags.push(br.readUInt8());
  }
  return info;
};

/**
 * @param {Object} - A plain JavaScript object
 * @returns {Block} - An instance of block
 */
MerkleBlock.fromObject = function fromObject(obj) {
  return new MerkleBlock(obj);
};

module.exports = MerkleBlock;
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();
var passport = require('passport');
var User = require('../models/User');

router.route('/')

  .get(function(req, res, next) { // return all leaders
    res.render('index', { title: 'GET /leaders/' });
  })

  .post(function(req, res, next) { // add a new leader (admin)
    res.render('index', { title: 'POST /leaders/' });
  })

  .delete(function(req, res, next) { // delete all leaders (admin)
    res.render('index', { title: 'DELETE /leaders/' });
  })
; // end route('/')

router.route('/:leaderID')

  .get(function(req, res, next) { // return a leader
    var leader = req.params.leaderID;
    res.render('index', { title: 'GET /leaders/ ' + leader });
  })

  .put(function(req, res, next) { // update a leader (admin)
    var leader = req.params.leaderID;
    res.render('index', { title: 'PUT /leaders/ ' + leader });
  })

  .delete(function(req, res, next) { // delete a leader (admin)
    var leader = req.params.leaderID;
    res.render('index', { title: 'DELETE /leaders/ ' + leader });
  })
; // end route('/:leaderID')

module.exports = router;
<commit_msg>Add CRUD support for leaders controller<commit_after>var express = require('express');
var router = express.Router();
var passport = require('passport');
var User = require('../models/User');
var Leader = require('../models/Leader');

router.route('/')

  .get(function(req, res, next) { // return all leaders

    Leader.find({}, function(err, results) {
      if (err) next(err);
      let statusCode = results.length ? 200 : 404;
      return res.status(statusCode).json({
        results: results,
        count: results.length,
        status: results.length ? "OK" : "No results found",
        statusCode: statusCode
      });
    });
  })

  .post(function(req, res, next) { // add a new leader (admin)

    let doc = {};
    doc.name = req.body.name || null;
    doc.image = req.body.image || null;
    doc.designation = req.body.designation || null;
    doc.abbr = req.body.abbr || null;
    doc.description = req.body.description || null;

    // @todo validate info
    // @todo add support for image upload

    let invalidFields = [];
    for (let field in doc) {
      if (field === null) invalidFields.push(field);
    }

    if (invalidFields.length > 0) {
      var response = {results: invalidFields, status: "Some fields were invalid", statusCode: 400};
      return res.status(response.statusCode).json(response);
    }

    Leader.find({}, function(err, results) {
      if (err) next(err);
      if (results.length > 0) return res.status(400).json({results: results, status: "That leader already exists", statusCode: 400});
    });

    Leader.create(doc, function(err, results) {
      if (err) {
        next(err);
      } else {
        var statusCode = 201;
        return res.status(statusCode).json({
          results: results,
          status: "Leader created",
          statusCode: statusCode
        });
      }

    });
  })

  .delete(function(req, res, next) { // delete all leaders (admin)

    Leader.remove({}, function(err, results) {
      if (err) next(err);
      return res.status(200).json({results: results, status: "Deleted all leaders", statusCode: 200});
    });
  })
; // end route('/')

router.route('/:leader')

  .get(function(req, res, next) { // return a leader
    var leader = req.params.leader;

    Leader.find({name: leader}, function(err, results) {
      if (err) next(err);
      let statusCode = results.length ? 200 : 404;
      return res.status(statusCode).json({
        results: results,
        count: results.length,
        status: results.length ? "OK" : "No results found",
        statusCode: statusCode
      });
    });
  })

  .put(function(req, res, next) { // update a leader (admin)
    var leader = req.params.leader;

    let doc = {};
    if ("image" in req.body) doc.image = req.body.image;
    if ("designation" in req.body) doc.designation = req.body.designation;
    if ("abbr" in req.body) doc.abbr = req.body.abbr;
    if ("description" in req.body) doc.description = req.body.description;

    // @todo validate info

    Leader.update({name: leader}, doc, {runValidators: true}, function(err, raw) {
      if (err) next(err);
      let statusCode = raw.nModified ? 200 : 304;
      return res.status(statusCode).json({
        results: raw,
        status: raw.nModified ? "OK" : "Not modified",
        statusCode: statusCode
      });
    });
  })

  .delete(function(req, res, next) { // delete a leader (admin)
    var leader = req.params.leader;

    Leader.remove({name: leader}, function(err, results) {
      if (err) next(err);
      return res.status(200).json({results: results, status: "Deleted leader " + leader, statusCode: 200});
    });
  })
; // end route('/:leaderID')

module.exports = router;
<|endoftext|>


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

// Data from GRCh38
// c.f. http://bioviz.org/quickload//H_sapiens_Dec_2013/
// c.f. http://www.ncbi.nlm.nih.gov/projects/genome/assembly/grc/human/data/
var INCLUDED_CHROMOSOME_NAMES = ["chr1", "chr2", "chr3", "chr4", "chr5", "chr6",
                                 "chr7", "chr8", "chr9", "chr10", "chr11", "chr12",
                                 "chr13", "chr14", "chr15", "chr16", "chr17",
                                 "chr18", "chr19", "chr20", "chr21", "chr22",
                                 "chrX", "chrY"];
var IDIOGRAM_HEIGHT = 7;
var CENTROMERE_RADIUS = 1.5;
var ARM_CLIP_RADIUS = 10;
var INITIAL_SCALE = 1;
var MAX_ZOOM_SCALE = 1000;

function drawChromosomes(selector, cytobands) {
  var data = cytobandsToChromosomes(cytobands),
      width = 800,
      height = 100,
      margin = {top: 50, bottom: 20, left: 20, right: 50},
      xscale = d3.scale.linear()
        .domain([0, data.totalBases])
        .range([0, width - margin.left - margin.right]),
      fullXDomain = xscale.domain(),
      curScale = INITIAL_SCALE;

  window.data = data;

  appendSvg();
  appendDna();
  appendListenerBox();
  initializeMouseListener();
  redraw(curScale, data.totalBases/2);

  function redraw(scale, pivot) {
    var chromosomes = d3.selectAll('.chromosome');
    var xMax, xMin;

    if (curScale <= scale) {
      var tscale = scale / curScale;
      xMax = ((xscale.domain()[1] - pivot) / tscale) + pivot;
      xMin = pivot - ((pivot - xscale.domain()[0]) / tscale);
    } else {
      var tscale = curScale / scale;
      xMax = ((xscale.domain()[1] - pivot) * tscale) + pivot;
      xMin = pivot - ((pivot - xscale.domain()[0]) * tscale);
    }
    curScale = scale;
    xscale.domain([xMin, xMax]);

    appendArmClips(chromosomes, xscale);

    chromosomes
        .attr('transform', function(d) {
          return 'translate(' + xscale(d.start) + ',0)';
        });

    chromosomes
      .selectAll('.band')
        .attr('x', function(d) { return xscale(xMin + d.start); }) // xMin required because these coords are within-chromosome
        .attr('width', function(d) { return xscale(xMin + d.end - d.start); })
        .attr('clip-path', function(d) {
          if ((d.end + d.chromosome.start) <= d.chromosome.center) // then we're in the P arm
            return 'url(#' + d.chromosomeName + '-clipper-P' + ')';
          else // well, then we're in the Q arm
            return 'url(#' + d.chromosomeName + '-clipper-Q' + ')';
        });

    chromosomes
      .selectAll('.centromere')
        .attr('cx', function(d) {
          return xscale(xMin + d.center - d.start);
        })
        .attr('cy', IDIOGRAM_HEIGHT/2)
        .attr('fill', '#FF3333')
        .attr('r', CENTROMERE_RADIUS);
  }

  function appendListenerBox() {
    return d3.select('svg g').append('rect')
      .attr('id', 'listener')
      .attr('width', width)
      .attr('height', height)
      .attr('x', -margin.left)
      .attr('y', -margin.top)
      .attr('fill', 'blue')
      .attr('opacity', 0);
  }

  function initializeMouseListener() {
    var zoomer = d3.behavior.zoom()
          .scaleExtent([1, MAX_ZOOM_SCALE])
          .on("zoom", zoom);

    d3.select('#listener')
        .on('mousemove', move)
        .call(zoomer);
  }

  function zoom() {
    redraw(d3.event.scale, bpFromMouse(d3.mouse(this)));
    d3.select('svg g').node().appendChild(d3.select('svg').select('#listener').node());
  }

  function move() {
    var bp = bpFromMouse(d3.mouse(this)),
        fmtBp = d3.format(',')(bp);

    console.log(fmtBp, d3.mouse(this), xscale.range());
  }

  function appendSvg() {
    return d3.select(selector)
      .append('svg')
        .attr('width', width)
        .attr('height', height)
      .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  }

  function bpFromMouse(mouse) {
    var mouseX = mouse[0], bp;
    bp = Math.round(xscale.invert(mouseX));
    return bp;
  }

  function appendDna() {
    var chromosomes = d3.select('svg g').selectAll('.chromosome')
        .data(data)
      .enter().append('g')
        .attr('class', 'chromosome');

    chromosomes.selectAll('.band')
        .data(function(d) { return d.values; })
      .enter().append('rect')
        .attr('class', 'band')
        .style('shape-rendering', 'crispEdges')
        .attr('fill', gstainFiller)
        .attr('y', 0)
        .attr('height', IDIOGRAM_HEIGHT);

    chromosomes.selectAll('.centromere')
        .data(function(d) { return [d]; })
      .enter().append('circle')
        .attr('class', 'centromere');
  }

}

function getter(attr) {
  return function(d) {
    return d[attr];
  }
}

function within(val, range, end) {
  var start;
  if (!end) {
    start = range[0];
    end = range[1];
  }
  return val >= start && val <= end;
}

function gstainFiller(d) {
  var stain = d.gstain;
  if (stain === 'gneg') {
    return '#dfdfdf';
  } else if (stain === 'gpos') {
    return '#525252';
  } else if (stain === 'acen') {
    return null;
  } else if (stain === 'gvar') {
    return '#cfcfcf';
  } else if (stain === 'stalk') {
    return '#cfcfcf';
  } else {
    return 'white';
  }
}

function chromosomeComparator(k1, k2) {
  k1 = k1.slice(3);
  k2 = k2.slice(3);

  if (k1 === 'X' || k1 === 'Y' || k2 === 'X' || k2 === 'Y') {
    if ((k1 === 'X' || k1 === 'Y') && (k2 === 'X' || k2 === 'Y')) {
      // Both are X, Y, Y comes second.
      return k1 === 'Y' ? 1 : -1;
    } else {
      // Then just one of them is X or Y, whichever is comes second.
      return ['X', 'Y'].indexOf(k1) === -1 ? -1 : 1;
    }
  }

  k1 = parseInt(k1);
  k2 = parseInt(k2);

  return k1 > k2 ? 1 : -1;
}

function addPQArms(chromosome) {
  var bands = chromosome.values;

  var centerP = bands.filter(function(d) {
    return d.gstain === 'acen' && d.bandname[0] === 'p';
  });

  var centerQ = bands.filter(function(d) {
    return d.gstain === 'acen' && d.bandname[0] === 'q';
  });

  chromosome.pArm = { start: chromosome.start };
  chromosome.qArm = { end: chromosome.end };

  if (centerP.length > 0)
    chromosome.pArm.end = chromosome.start + centerP[0].end;
  if (centerQ.length > 0)
    chromosome.qArm.start = chromosome.start + centerQ[0].start;
}

function cytobandsToChromosomes(cytobands) {
  // Remove the contigs we don't care about.
  cytobands = cytobands.filter(function(d) {
    return INCLUDED_CHROMOSOME_NAMES.indexOf(d.chromosomeName) != -1;
  });

  // Group bands by chromosomes
  var chromosomes = d3.nest()
    .key(getter('chromosomeName'))
    .sortKeys(chromosomeComparator)
    .entries(cytobands);

  // Add metainformation to each chromosome
  var totalBases = 0;
  for (var i in chromosomes) {
    var bands = chromosomes[i].values;
    var chromosomeLength = d3.max(bands, getter('end'));
    chromosomes[i].basePairs = chromosomeLength;
    chromosomes[i].start = totalBases;
    totalBases += chromosomeLength;
    chromosomes[i].end = totalBases;

    addPQArms(chromosomes[i]);
    bands.map(function(d) {
      d.chromosome = chromosomes[i];
    });
    chromosomes[i].center = chromosomes[i].pArm.end;
  }
  chromosomes.totalBases = totalBases;

  // TODO(ihodes): Debug statement below:
  window.c = chromosomes;

  return chromosomes;
}

function appendArmClips(chromosomes, xscale) {
  var xMin = xscale.domain()[0];

  d3.selectAll('.clipper').remove();

  chromosomes
    .append('g')
      .attr('class', 'clipper')
    .append('clipPath')
      .attr('id', function(d) {
        return d.key + '-clipper-P';
      })
    .append('rect')
      .attr('y', 0)
      .attr('height', IDIOGRAM_HEIGHT)
      .attr('x', 0)  // xMin required because these coords are within-chromosome
      .attr('width', function(d) { return xscale(xMin + d.pArm.end - d.pArm.start); })
      .attr('rx', ARM_CLIP_RADIUS)
      .attr('ry', ARM_CLIP_RADIUS);

  chromosomes
    .append('g')
      .attr('class', 'clipper')
    .append('clipPath')
      .attr('id', function(d) {
        return d.key + '-clipper-Q';
      })
    .append('rect')
      .attr('y', 0)
      .attr('height', IDIOGRAM_HEIGHT)  // xMin required because these coords are within-chromosome
      .attr('x', function(d) { return xscale(xMin + d.pArm.end - d.pArm.start); })
      .attr('width', function(d) { return xscale(xMin + d.qArm.end - d.qArm.start); })
      .attr('rx', ARM_CLIP_RADIUS)
      .attr('ry', ARM_CLIP_RADIUS);
}

function main(selector) {
  d3.tsv('cytoband.tsv',
         function(d) {
           return {
             chromosomeName: d.chromosomeName,
             start: parseInt(d.start, 10),
             end: parseInt(d.end, 10),
             bandname: d.bandname,
             gstain: d.gstain
           };
         },
         function(err, data) {
           if (err) {
             console.log('There was an error loading the cytoband data.');
           } else {
             drawChromosomes(selector, data);
           }
         });
}

main('body');

window.idiogrammatik = {};

})()
<commit_msg>Basic, terrible, panning.<commit_after>(function() {
"use strict";

// Data from GRCh38
// c.f. http://bioviz.org/quickload//H_sapiens_Dec_2013/
// c.f. http://www.ncbi.nlm.nih.gov/projects/genome/assembly/grc/human/data/
var INCLUDED_CHROMOSOME_NAMES = ["chr1", "chr2", "chr3", "chr4", "chr5", "chr6",
                                 "chr7", "chr8", "chr9", "chr10", "chr11", "chr12",
                                 "chr13", "chr14", "chr15", "chr16", "chr17",
                                 "chr18", "chr19", "chr20", "chr21", "chr22",
                                 "chrX", "chrY"];
var IDIOGRAM_HEIGHT = 7;
var CENTROMERE_RADIUS = 1.5;
var ARM_CLIP_RADIUS = 10;
var INITIAL_SCALE = 1;
var MAX_ZOOM_SCALE = 1000;

function drawChromosomes(selector, cytobands) {
  var data = cytobandsToChromosomes(cytobands),
      width = 800,
      height = 100,
      margin = {top: 50, bottom: 20, left: 20, right: 50},
      xscale = d3.scale.linear()
        .domain([0, data.totalBases])
        .range([0, width - margin.left - margin.right]),
      fullXDomain = xscale.domain(), // used for scaling
      curScale = INITIAL_SCALE, // used for scaling
      lastBp; // used for dragging

  window.data = data;

  appendSvg();
  appendDna();
  appendListenerBox();
  initializeMouseListener();
  redraw(curScale, data.totalBases/2);

  function redraw(scale, pivot, shiftBp) {
    var chromosomes = d3.selectAll('.chromosome');
    var xMax, xMin;

    if (scale) {
      if (curScale <= scale) {
        var tscale = scale / curScale;
        xMin = pivot - ((pivot - xscale.domain()[0]) / tscale);
        xMax = ((xscale.domain()[1] - pivot) / tscale) + pivot;
      } else {
        var tscale = curScale / scale;
        xMin = pivot - ((pivot - xscale.domain()[0]) * tscale);
        xMax = ((xscale.domain()[1] - pivot) * tscale) + pivot;
      }
      curScale = scale;
    }

    if (shiftBp) {
      xMin = xscale.domain()[0] - shiftBp;
      xMax = xscale.domain()[1] - shiftBp;
    }

    if (shiftBp || scale)
      xscale.domain([xMin, xMax]);

    appendArmClips(chromosomes, xscale);

    chromosomes
        .attr('transform', function(d) {
          return 'translate(' + xscale(d.start) + ',0)';
        });

    chromosomes
      .selectAll('.band')
        .attr('x', function(d) { return xscale(xMin + d.start); }) // xMin required because these coords are within-chromosome
        .attr('width', function(d) { return xscale(xMin + d.end - d.start); })
        .attr('clip-path', function(d) {
          if ((d.end + d.chromosome.start) <= d.chromosome.center) // then we're in the P arm
            return 'url(#' + d.chromosomeName + '-clipper-P' + ')';
          else // well, then we're in the Q arm
            return 'url(#' + d.chromosomeName + '-clipper-Q' + ')';
        });

    chromosomes
      .selectAll('.centromere')
        .attr('cx', function(d) {
          return xscale(xMin + d.center - d.start);
        })
        .attr('cy', IDIOGRAM_HEIGHT/2)
        .attr('fill', '#FF3333')
        .attr('r', CENTROMERE_RADIUS);

    d3.select('svg g').node().appendChild(d3.select('svg').select('#listener').node());
  }

  function appendListenerBox() {
    return d3.select('svg g').append('rect')
      .attr('id', 'listener')
      .attr('width', width)
      .attr('height', height)
      .attr('x', -margin.left)
      .attr('y', -margin.top)
      .attr('fill', 'blue')
      .attr('opacity', 0);
  }

  function initializeMouseListener() {
    var zoomer = d3.behavior.zoom()
          .scaleExtent([1, MAX_ZOOM_SCALE])
          .on("zoom", zoom);

    var dragger = d3.behavior.drag()
          .on("dragstart", function() {
            lastBp = bpFromMouse(d3.mouse(this));
          })
          .on("drag", drag);

    d3.select('#listener')
        .on('mousemove', move)
        .call(zoomer)
        .call(dragger);
  }

  function zoom() {
    redraw(d3.event.scale, bpFromMouse(d3.mouse(this)));
  }

  function drag() {
    var curBp = bpFromMouse(d3.mouse(this));

    redraw(null, curBp, curBp - lastBp);
  }

  function move() {
    var bp = bpFromMouse(d3.mouse(this)),
        fmtBp = d3.format(',')(bp);

//    console.log(fmtBp, d3.mouse(this), xscale.range());
  }

  function appendSvg() {
    return d3.select(selector)
      .append('svg')
        .attr('width', width)
        .attr('height', height)
      .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
  }

  function bpFromMouse(mouse) {
    var mouseX = mouse[0], bp;
    bp = Math.round(xscale.invert(mouseX));
    return bp;
  }

  function appendDna() {
    var chromosomes = d3.select('svg g').selectAll('.chromosome')
        .data(data)
      .enter().append('g')
        .attr('class', 'chromosome');

    chromosomes.selectAll('.band')
        .data(function(d) { return d.values; })
      .enter().append('rect')
        .attr('class', 'band')
        .style('shape-rendering', 'crispEdges')
        .attr('fill', gstainFiller)
        .attr('y', 0)
        .attr('height', IDIOGRAM_HEIGHT);

    chromosomes.selectAll('.centromere')
        .data(function(d) { return [d]; })
      .enter().append('circle')
        .attr('class', 'centromere');
  }

}

function getter(attr) {
  return function(d) {
    return d[attr];
  }
}

function within(val, range, end) {
  var start;
  if (!end) {
    start = range[0];
    end = range[1];
  }
  return val >= start && val <= end;
}

function gstainFiller(d) {
  var stain = d.gstain;
  if (stain === 'gneg') {
    return '#dfdfdf';
  } else if (stain === 'gpos') {
    return '#525252';
  } else if (stain === 'acen') {
    return null;
  } else if (stain === 'gvar') {
    return '#cfcfcf';
  } else if (stain === 'stalk') {
    return '#cfcfcf';
  } else {
    return 'white';
  }
}

function chromosomeComparator(k1, k2) {
  k1 = k1.slice(3);
  k2 = k2.slice(3);

  if (k1 === 'X' || k1 === 'Y' || k2 === 'X' || k2 === 'Y') {
    if ((k1 === 'X' || k1 === 'Y') && (k2 === 'X' || k2 === 'Y')) {
      // Both are X, Y, Y comes second.
      return k1 === 'Y' ? 1 : -1;
    } else {
      // Then just one of them is X or Y, whichever is comes second.
      return ['X', 'Y'].indexOf(k1) === -1 ? -1 : 1;
    }
  }

  k1 = parseInt(k1);
  k2 = parseInt(k2);

  return k1 > k2 ? 1 : -1;
}

function addPQArms(chromosome) {
  var bands = chromosome.values;

  var centerP = bands.filter(function(d) {
    return d.gstain === 'acen' && d.bandname[0] === 'p';
  });

  var centerQ = bands.filter(function(d) {
    return d.gstain === 'acen' && d.bandname[0] === 'q';
  });

  chromosome.pArm = { start: chromosome.start };
  chromosome.qArm = { end: chromosome.end };

  if (centerP.length > 0)
    chromosome.pArm.end = chromosome.start + centerP[0].end;
  if (centerQ.length > 0)
    chromosome.qArm.start = chromosome.start + centerQ[0].start;
}

function cytobandsToChromosomes(cytobands) {
  // Remove the contigs we don't care about.
  cytobands = cytobands.filter(function(d) {
    return INCLUDED_CHROMOSOME_NAMES.indexOf(d.chromosomeName) != -1;
  });

  // Group bands by chromosomes
  var chromosomes = d3.nest()
    .key(getter('chromosomeName'))
    .sortKeys(chromosomeComparator)
    .entries(cytobands);

  // Add metainformation to each chromosome
  var totalBases = 0;
  for (var i in chromosomes) {
    var bands = chromosomes[i].values;
    var chromosomeLength = d3.max(bands, getter('end'));
    chromosomes[i].basePairs = chromosomeLength;
    chromosomes[i].start = totalBases;
    totalBases += chromosomeLength;
    chromosomes[i].end = totalBases;

    addPQArms(chromosomes[i]);
    bands.map(function(d) {
      d.chromosome = chromosomes[i];
    });
    chromosomes[i].center = chromosomes[i].pArm.end;
  }
  chromosomes.totalBases = totalBases;

  // TODO(ihodes): Debug statement below:
  window.c = chromosomes;

  return chromosomes;
}

function appendArmClips(chromosomes, xscale) {
  var xMin = xscale.domain()[0];

  d3.selectAll('.clipper').remove();

  chromosomes
    .append('g')
      .attr('class', 'clipper')
    .append('clipPath')
      .attr('id', function(d) {
        return d.key + '-clipper-P';
      })
    .append('rect')
      .attr('y', 0)
      .attr('height', IDIOGRAM_HEIGHT)
      .attr('x', 0)  // xMin required because these coords are within-chromosome
      .attr('width', function(d) { return xscale(xMin + d.pArm.end - d.pArm.start); })
      .attr('rx', ARM_CLIP_RADIUS)
      .attr('ry', ARM_CLIP_RADIUS);

  chromosomes
    .append('g')
      .attr('class', 'clipper')
    .append('clipPath')
      .attr('id', function(d) {
        return d.key + '-clipper-Q';
      })
    .append('rect')
      .attr('y', 0)
      .attr('height', IDIOGRAM_HEIGHT)  // xMin required because these coords are within-chromosome
      .attr('x', function(d) { return xscale(xMin + d.pArm.end - d.pArm.start); })
      .attr('width', function(d) { return xscale(xMin + d.qArm.end - d.qArm.start); })
      .attr('rx', ARM_CLIP_RADIUS)
      .attr('ry', ARM_CLIP_RADIUS);
}

function main(selector) {
  d3.tsv('cytoband.tsv',
         function(d) {
           return {
             chromosomeName: d.chromosomeName,
             start: parseInt(d.start, 10),
             end: parseInt(d.end, 10),
             bandname: d.bandname,
             gstain: d.gstain
           };
         },
         function(err, data) {
           if (err) {
             console.log('There was an error loading the cytoband data.');
           } else {
             drawChromosomes(selector, data);
           }
         });
}

main('body');

window.idiogrammatik = {};

})()
<|endoftext|>


<commit_before>/**
 * 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.
 */

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import _ from 'lodash';

import * as actions from '../../redux/actions';

import LoginNav from '../../components/loginnav';
import LoginLogo from '../../components/loginlogo';
import SimpleForm from '../../components/simpleform';

import utils from '../../core/utils';

export var EmailVerification = React.createClass({
  propTypes: {
    acknowledgeNotification: React.PropTypes.func.isRequired,
    notification: React.PropTypes.object,
    onSubmitResend: React.PropTypes.func.isRequired,
    resent: React.PropTypes.bool.isRequired,
    sent: React.PropTypes.oneOfType([
      React.PropTypes.bool,
      React.PropTypes.string,
    ]),
    trackMetric: React.PropTypes.func.isRequired,
    working: React.PropTypes.bool.isRequired
  },
  componentWillUnmount: function() {
    this.props.acknowledgeNotification('resendingEmailVerification');
  },
  formInputs: function() {
    return [
      {name: 'email', label: 'Email', type: 'email'}
    ];
  },
  getInitialState: function() {
    return {
      formValues: {},
      validationErrors: {}
    };
  },
  render: function() {
    var content;
    var loginPage;

    if (this.props.sent) {
      loginPage = 'signup';
      content = (

Keeping your data private and secure is important to us!

Please click the link in the email we just sent you at {this.props.sent} to verify and activate your account.

      );
    }
    else {
      loginPage = 'login';
      content = (

Hey, you're not verified yet.

Check your email and follow the link there. (We need to confirm that you are really you.)

Do you want us to resend the email? Enter the address you used to signup below.

{this.renderForm()}

      );
    }

    return (

        <LoginNav
          page={loginPage}
          hideLinks={false}
          trackMetric={this.props.trackMetric} />
        <LoginLogo />
        {content}

    );
  },
  renderForm: function() {
    var submitButtonText = this.props.working ? 'Sending email...' : 'Resend';

    return (
      <SimpleForm
        inputs={this.formInputs()}
        formValues={this.state.formValues}
        validationErrors={this.state.validationErrors}
        submitButtonText={submitButtonText}
        submitDisabled={this.props.working}
        onSubmit={this.handleSubmit}
        notification={this.props.notification}/>
    );
  },
  handleSubmit: function(formValues) {
    var self = this;

    if (this.props.working) {
      return;
    }

    this.resetFormStateBeforeSubmit(formValues);

    var validationErrors = this.validateFormValues(formValues);
    if (!_.isEmpty(validationErrors)) {
      return;
    }
    this.props.onSubmitResend(formValues.email);
  },
  resetFormStateBeforeSubmit: function(formValues) {
    this.props.acknowledgeNotification('resendingEmailVerification');
    this.setState({
      formValues: formValues,
      validationErrors: {}
    });
  },
  validateFormValues: function(formValues) {
    var validationErrors = {};
    var IS_REQUIRED = 'This field is required.';
    var INVALID_EMAIL = 'Invalid email address.';

    if (!formValues.email) {
      validationErrors.email = IS_REQUIRED;
    }

    if (formValues.email && !utils.validateEmail(formValues.email)) {
      validationErrors.email = INVALID_EMAIL;
    }

    if (!_.isEmpty(validationErrors)) {
      this.setState({
        validationErrors: validationErrors
      });
    }

    return validationErrors;
  }
});

/**
 * Expose "Smart" Component that is connect-ed to Redux
 */

export function mapStateToProps(state) {
  return {
    notification: state.blip.working.resendingEmailVerification.notification,
    working: state.blip.working.resendingEmailVerification.inProgress,
    resent: state.blip.resentEmailVerification,
    sent: state.blip.sentEmailVerification
  };
}

let mapDispatchToProps = dispatch => bindActionCreators({
  submitResend: actions.async.resendEmailVerification,
  acknowledgeNotification: actions.sync.acknowledgeNotification
}, dispatch);

let mergeProps = (stateProps, dispatchProps, ownProps) => {
  var api = ownProps.routes[0].api;
  return Object.assign({}, stateProps, _.omit(dispatchProps, 'submitResend'), {
    onSubmitResend: dispatchProps.submitResend.bind(null, api),
    trackMetric: ownProps.routes[0].trackMetric
  });
};

export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(EmailVerification);

<commit_msg>Split email verification address to it's own line<commit_after>/**
 * 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.
 */

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import _ from 'lodash';

import * as actions from '../../redux/actions';

import LoginNav from '../../components/loginnav';
import LoginLogo from '../../components/loginlogo';
import SimpleForm from '../../components/simpleform';

import utils from '../../core/utils';

export var EmailVerification = React.createClass({
  propTypes: {
    acknowledgeNotification: React.PropTypes.func.isRequired,
    notification: React.PropTypes.object,
    onSubmitResend: React.PropTypes.func.isRequired,
    resent: React.PropTypes.bool.isRequired,
    sent: React.PropTypes.oneOfType([
      React.PropTypes.bool,
      React.PropTypes.string,
    ]),
    trackMetric: React.PropTypes.func.isRequired,
    working: React.PropTypes.bool.isRequired
  },
  componentWillUnmount: function() {
    this.props.acknowledgeNotification('resendingEmailVerification');
  },
  formInputs: function() {
    return [
      {name: 'email', label: 'Email', type: 'email'}
    ];
  },
  getInitialState: function() {
    return {
      formValues: {},
      validationErrors: {}
    };
  },
  render: function() {
    var content;
    var loginPage;

    if (this.props.sent) {
      loginPage = 'signup';
      content = (

Keeping your data private and secure is important to us!

              Please click the link in the email we just sent you at

                {this.props.sent}

              to verify and activate your account.

      );
    }
    else {
      loginPage = 'login';
      content = (

Hey, you're not verified yet.

Check your email and follow the link there. (We need to confirm that you are really you.)

Do you want us to resend the email? Enter the address you used to signup below.

{this.renderForm()}

      );
    }

    return (

        <LoginNav
          page={loginPage}
          hideLinks={false}
          trackMetric={this.props.trackMetric} />
        <LoginLogo />
        {content}

    );
  },
  renderForm: function() {
    var submitButtonText = this.props.working ? 'Sending email...' : 'Resend';

    return (
      <SimpleForm
        inputs={this.formInputs()}
        formValues={this.state.formValues}
        validationErrors={this.state.validationErrors}
        submitButtonText={submitButtonText}
        submitDisabled={this.props.working}
        onSubmit={this.handleSubmit}
        notification={this.props.notification}/>
    );
  },
  handleSubmit: function(formValues) {
    var self = this;

    if (this.props.working) {
      return;
    }

    this.resetFormStateBeforeSubmit(formValues);

    var validationErrors = this.validateFormValues(formValues);
    if (!_.isEmpty(validationErrors)) {
      return;
    }
    this.props.onSubmitResend(formValues.email);
  },
  resetFormStateBeforeSubmit: function(formValues) {
    this.props.acknowledgeNotification('resendingEmailVerification');
    this.setState({
      formValues: formValues,
      validationErrors: {}
    });
  },
  validateFormValues: function(formValues) {
    var validationErrors = {};
    var IS_REQUIRED = 'This field is required.';
    var INVALID_EMAIL = 'Invalid email address.';

    if (!formValues.email) {
      validationErrors.email = IS_REQUIRED;
    }

    if (formValues.email && !utils.validateEmail(formValues.email)) {
      validationErrors.email = INVALID_EMAIL;
    }

    if (!_.isEmpty(validationErrors)) {
      this.setState({
        validationErrors: validationErrors
      });
    }

    return validationErrors;
  }
});

/**
 * Expose "Smart" Component that is connect-ed to Redux
 */

export function mapStateToProps(state) {
  return {
    notification: state.blip.working.resendingEmailVerification.notification,
    working: state.blip.working.resendingEmailVerification.inProgress,
    resent: state.blip.resentEmailVerification,
    sent: state.blip.sentEmailVerification
  };
}

let mapDispatchToProps = dispatch => bindActionCreators({
  submitResend: actions.async.resendEmailVerification,
  acknowledgeNotification: actions.sync.acknowledgeNotification
}, dispatch);

let mergeProps = (stateProps, dispatchProps, ownProps) => {
  var api = ownProps.routes[0].api;
  return Object.assign({}, stateProps, _.omit(dispatchProps, 'submitResend'), {
    onSubmitResend: dispatchProps.submitResend.bind(null, api),
    trackMetric: ownProps.routes[0].trackMetric
  });
};

export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(EmailVerification);

<|endoftext|>


<commit_before>/*
 * Copyright [1999-2014] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * speciesDropdown: Javascript counterpart for E::W::Form::Element::SpeciesDropdown
 * Extension of filterableDropdown to add species icons to the tags
 * Reserverd classname prefix: _sdd
 **/
(function ($) {
  $.fn.speciesDropdown = function (options) {
  /*
   * options: same as accepted by filterableDropdown
   */

    return this.each(function () {
      $.speciesDropdown($(this), options);
    });
  };

  $.speciesDropdown = function (el, options) {

    if (options && options.change) {
      el.data('speciesDropdown', { change: options.change });
    }

    $.filterableDropdown(el, $.extend({}, options, {
      'change': function() {
        var data = $(this).find('._fd_tag').css('background-image', function() {
          return this.style.backgroundImage.replace(/[^\/]+\.png/, $($(this).data('input')).val() + '.png');
        }).end().data('speciesDropdown');
        if (data) {
          data.change.apply(this, arguments);
        }
        data = null;
      }
    }));
  };
})(jQuery);<commit_msg>IE doesn't set the background picture<commit_after>/*
 * Copyright [1999-2014] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * speciesDropdown: Javascript counterpart for E::W::Form::Element::SpeciesDropdown
 * Extension of filterableDropdown to add species icons to the tags
 * Reserverd classname prefix: _sdd
 **/
(function ($) {
  $.fn.speciesDropdown = function (options) {
  /*
   * options: same as accepted by filterableDropdown
   */

    return this.each(function () {
      $.speciesDropdown($(this), options);
    });
  };

  $.speciesDropdown = function (el, options) {

    if (options && options.change) {
      el.data('speciesDropdown', { change: options.change });
    }

    $.filterableDropdown(el, $.extend({}, options, {
      'change': function() {
        var data = $(this).find('._fd_tag').each(function() {
          this.style.backgroundImage = this.style.backgroundImage.replace(/[^\/]+\.png/, $($(this).data('input')).val() + '.png');
        }).end().data('speciesDropdown');
        if (data) {
          data.change.apply(this, arguments);
        }
        data = null;
      }
    }));
  };
})(jQuery);<|endoftext|>


<commit_before>$(function() {

      /**
       *
       * Set the connect page + room number so the user knows where he has to go to connect
       *
       */

      $('.browser').html(url.currentURL + '/connect.html');
      $('.room_id').html(room.id);
});

var mobile = {
      connected: false
};

url.check();
room.setID();

/*
|------------------------------------------------------------------------------------
| Connect to socket.io
|------------------------------------------------------------------------------------
*/

var socket = io.connect(url.currentURL);

/**
 *
 * Connect to a room
 *
 */

socket.on('connect', function() {
      //console.log('main.js connect', room.id);
      socket.emit('message', {
            msg: 'you are connected to the room ' + room.id
      })
      socket.emit('room', room.id);
});

/**
 *
 * Do stuff when user is connected
 *
 */

socket.on('connected_person', function(data) {
      console.log('A new user (mobile) is connected');
      if (room.id == data) {
            basket.start = true;

            // $('.info').fadeOut();

            // $('.info-score').addClass('active');

            $('.chose_socket .play').removeClass('hide');

            basket.controller = "mobile";

            basket.showNotification('Smartphone Connection');

            // basket.pause();
      }
});

socket.on('shooting', function(data) {
      console.log('shoot', data.power);
      //shoot();

      mobile.power = data.power;
      basket.power = data.power;

      look.theUserIsShooting(mobile.position.gamma, mobile.position.beta);

});

socket.on('motiondatas', function(data) {

      //console.log('motiondatas', data);

      mobile.position = data;

      //moveRifle(data.gamma, data.beta);

      look.AtTheObjectsMove(data.gamma, data.beta);
});

socket.on('mobile_disconnect', function() {
      console.log('lost connection')

      if (basket.controller == 'mobile') {
            basket.showNotification('Smartphone Connection lost')
            basket.pause();
      }

      // if (!game.paused) {
      //       game.updatePauseMessage();
      //       game.pause();
      // }
});

socket.on('user_power', function(data) {

      // console.log('power', data.power);
      //  if(data.power <= 5) {
      //     data.color = 'orange';
      //   }

      //   if(data.power == 6 ) {
      //     data.color = 'green';
      //   }

      //   if(data.power >= 7) {
      //     data.color = 'red';
      //   }

      if (basket.start) {
            $('.powerIndicator').css({
                  'bottom': 30 * data.power
            });
      }
})<commit_msg>phone connection<commit_after>$(function() {

      /**
       *
       * Set the connect page + room number so the user knows where he has to go to connect
       *
       */

      $('.browser').html(url.currentURL + '/connect.html');
      $('.room_id').html(room.id);
});

var mobile = {
      connected: false
};

url.check();
room.setID();

/*
|------------------------------------------------------------------------------------
| Connect to socket.io
|------------------------------------------------------------------------------------
*/

var socket = io.connect(url.currentURL);

/**
 *
 * Connect to a room
 *
 */

socket.on('connect', function() {
      //console.log('main.js connect', room.id);
      socket.emit('message', {
            msg: 'you are connected to the room ' + room.id
      })
      socket.emit('room', room.id);
});

/**
 *
 * Do stuff when user is connected
 *
 */

socket.on('connected_person', function(data) {
      console.log('A new user (mobile) is connected');
      if (room.id == data) {
            basket.start = true;

            // $('.info').fadeOut();

            // $('.info-score').addClass('active');

            $('.chose_socket .play').removeClass('hide');

            basket.controller = "mobile";

            basket.showNotification('Smartphone Connection');

            // basket.pause();
      }
});

socket.on('shooting', function(data) {
      console.log('shoot', data.power);
      //shoot();

      mobile.power = data.power;
      basket.power = data.power;

      look.theUserIsShooting(mobile.position.gamma, mobile.position.beta);

});

socket.on('motiondatas', function(data) {

      //console.log('motiondatas', data);

      mobile.position = data;

      //moveRifle(data.gamma, data.beta);

      look.AtTheObjectsMove(data.gamma, data.beta);
});

socket.on('mobile_disconnect', function() {
      console.log('lost connection')

      if (basket.controller == 'mobile') {
            basket.showNotification('Smartphone Connection lost')

            if (basket.start && basket.infoVisible) {
                  basket.pause();
            }
      }

      // if (!game.paused) {
      //       game.updatePauseMessage();
      //       game.pause();
      // }
});

socket.on('user_power', function(data) {

      // console.log('power', data.power);
      //  if(data.power <= 5) {
      //     data.color = 'orange';
      //   }

      //   if(data.power == 6 ) {
      //     data.color = 'green';
      //   }

      //   if(data.power >= 7) {
      //     data.color = 'red';
      //   }

      if (basket.start) {
            $('.powerIndicator').css({
                  'bottom': 30 * data.power
            });
      }
})<|endoftext|>


<commit_before>var creep_asshealer = {

    /** @param {Creep} creep **/
    run: function(creep) {
        var unboostedTough = 0;
        var unboostedHeal = 0;
        var unboostedMove = 0;

        creep.body.forEach(function(thisPart) {
            if (thisPart.type == HEAL && !thisPart.boost) {
                unboostedHeal = unboostedHeal + 1;
            }

            if (thisPart.type == TOUGH && !thisPart.boost) {
                unboostedTough = unboostedTough + 1;
            }

            if (thisPart.type == MOVE && !thisPart.boost) {
                unboostedMove = unboostedMove + 1;
            }
        });

        if (!creep.memory.UnassignDelay) {
            creep.memory.UnassignDelay = 0;
        }

        if (Game.flags[creep.memory.homeRoom + "DoBoost"] && Game.flags[creep.memory.homeRoom + "RunningAssault"] && (unboostedMove > 0 || unboostedTough > 0 || unboostedHeal > 0)) {
            let MoveLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_ZYNTHIUM_ALKALIDE)
            });
            let ToughLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_GHODIUM_ALKALIDE)
            });
            var HealLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_LEMERGIUM_ALKALIDE)
            });
            let hasTraveled = false;
            if (MoveLab.length && unboostedMove > 0) {
                MoveLab[0].boostCreep(creep);
                creep.travelTo(MoveLab[0]);
                hasTraveled = true;
            }
            if (ToughLab.length && unboostedTough > 0) {
                if (!hasTraveled) {
                    creep.travelTo(ToughLab[0], {
                        ignoreRoads: true
                    });
                    hasTraveled = true;
                }
                ToughLab[0].boostCreep(creep);
            }
            if (HealLab.length && unboostedHeal > 0) {
                if (!hasTraveled) {
                    creep.travelTo(HealLab[0], {
                        ignoreRoads: true
                    });
                    hasTraveled = true;
                }
                HealLab[0].boostCreep(creep);
            }
        } else {
            var targetAttacker = Game.getObjectById(creep.memory.attackerID);
            if (targetAttacker) {
                var thisPortal = undefined;
                if (Game.flags["TakePortal"] && Game.flags["TakePortal"].pos.roomName == creep.pos.roomName) {
                    var thisPortal = creep.pos.findClosestByRange(FIND_STRUCTURES, {
                        filter: (structure) => (structure.structureType == STRUCTURE_PORTAL)
                    });
                }
                if (thisPortal) {
                    creep.travelTo(thisPortal, {
                        ignoreRoads: true
                    });
                } else if ((creep.pos.x == 0 || creep.pos.x == 49 || creep.pos.y == 0 || creep.pos.y == 49) && targetAttacker.room.name == creep.room.name) {
                    /*var xTarget = 0;
                    var yTarget = 0;
                    if (creep.pos.x == 0) {
                        xTarget = 2;
                        yTarget = creep.pos.y;
                    } else if (creep.pos.x == 49) {
                        xTarget = 47;
                        yTarget = creep.pos.y;
                    }
                    if (creep.pos.y == 0) {
                        yTarget = 2;
                        xTarget = creep.pos.x;
                    } else if (creep.pos.y == 49) {
                        yTarget = 47;
                        xTarget = creep.pos.x;
                    }

                    creep.moveTo(xTarget, yTarget);*/
                    creep.moveTo(targetAttacker.pos);
                } else {
                    /*if (creep.pos.inRangeTo(targetAttacker, 2)) {
                        creep.move(creep.pos.getDirectionTo(targetAttacker));
                    } else {*/
                    if (targetAttacker.room.name == creep.room.name) {
                        creep.travelTo(targetAttacker, {
                            maxRooms: 1,
                            ignoreRoads: true,
                            stuckValue: 2
                        });
                    } else {
                        creep.travelTo(targetAttacker, {
                            ignoreRoads: true,
                            stuckValue: 2
                        });
                    }
                    //}
                }

                if (creep.hits < creep.hitsMax - 400) {
                    creep.heal(creep);
                    creep.say("(=\u2716\u11BD\u2716=)", true);
                } else {

                    if (Game.time % 2 == 0) {
                        creep.say("(=\u25D5\u11BD\u25D5\u0E3A=)", true);
                    } else {
                        creep.say("(=\u229D\u11BD\u229D=)", true);
                    }

                    var hurtAlly = creep.pos.findInRange(FIND_CREEPS, 3, {
                        filter: (thisCreep) => thisCreep.hits < thisCreep.hitsMax - 600 && thisCreep.id != targetAttacker.id && (thisCreep.owner.username == "Montblanc" || Memory.whiteList.includes(thisCreep.owner.username))
                    });
                    var healedAlly = false
                    if (hurtAlly.length > 0) {
                        hurtAlly.sort(healCompare);
                        if (creep.pos.getRangeTo(hurtAlly[0]) > 1) {
                            if (creep.rangedHeal(hurtAlly[0]) == OK) {
                                healedAlly = true;
                            }
                        } else {
                            if (creep.heal(hurtAlly[0]) == OK) {
                                healedAlly = true;
                            }
                        }
                    }

                    if (!healedAlly) {
                        if (creep.pos.getRangeTo(targetAttacker) > 1) {
                            creep.rangedHeal(targetAttacker);
                        } else {
                            creep.heal(targetAttacker);
                        }
                    }
                }
            } else {
                creep.memory.UnassignDelay++;
                if (creep.memory.UnassignDelay > 10) {
                    creep.memory.priority = 'targetlessHealer';
                }
                creep.heal(creep);
                if (Game.flags[creep.memory.homeRoom + "RallyHere"] && Game.flags[creep.memory.homeRoom + "RallyHere"].pos) {
                    creep.travelTo(Game.flags[creep.memory.homeRoom + "RallyHere"], {
                        ignoreRoads: true
                    });
                }
                var newTarget = creep.pos.findInRange(FIND_MY_CREEPS, 10, {
                    filter: (mCreep) => (mCreep.memory.priority == "assattacker")
                });
                if (newTarget.length) {
                    creep.memory.attackerID = newTarget[0].id;
                }
            }
        }
    }

};

function healCompare(a, b) {
    if (a.hits < b.hits)
        return -1;
    if (a.hits > b.hits)
        return 1;
    return 0;
}

module.exports = creep_asshealer;<commit_msg>Minimize stuck time<commit_after>var creep_asshealer = {

    /** @param {Creep} creep **/
    run: function(creep) {
        var unboostedTough = 0;
        var unboostedHeal = 0;
        var unboostedMove = 0;

        creep.body.forEach(function(thisPart) {
            if (thisPart.type == HEAL && !thisPart.boost) {
                unboostedHeal = unboostedHeal + 1;
            }

            if (thisPart.type == TOUGH && !thisPart.boost) {
                unboostedTough = unboostedTough + 1;
            }

            if (thisPart.type == MOVE && !thisPart.boost) {
                unboostedMove = unboostedMove + 1;
            }
        });

        if (!creep.memory.UnassignDelay) {
            creep.memory.UnassignDelay = 0;
        }

        if (Game.flags[creep.memory.homeRoom + "DoBoost"] && Game.flags[creep.memory.homeRoom + "RunningAssault"] && (unboostedMove > 0 || unboostedTough > 0 || unboostedHeal > 0)) {
            let MoveLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_ZYNTHIUM_ALKALIDE)
            });
            let ToughLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_GHODIUM_ALKALIDE)
            });
            var HealLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_LEMERGIUM_ALKALIDE)
            });
            let hasTraveled = false;
            if (MoveLab.length && unboostedMove > 0) {
                MoveLab[0].boostCreep(creep);
                creep.travelTo(MoveLab[0]);
                hasTraveled = true;
            }
            if (ToughLab.length && unboostedTough > 0) {
                if (!hasTraveled) {
                    creep.travelTo(ToughLab[0], {
                        ignoreRoads: true
                    });
                    hasTraveled = true;
                }
                ToughLab[0].boostCreep(creep);
            }
            if (HealLab.length && unboostedHeal > 0) {
                if (!hasTraveled) {
                    creep.travelTo(HealLab[0], {
                        ignoreRoads: true
                    });
                    hasTraveled = true;
                }
                HealLab[0].boostCreep(creep);
            }
        } else {
            var targetAttacker = Game.getObjectById(creep.memory.attackerID);
            if (targetAttacker) {
                var thisPortal = undefined;
                if (Game.flags["TakePortal"] && Game.flags["TakePortal"].pos.roomName == creep.pos.roomName) {
                    var thisPortal = creep.pos.findClosestByRange(FIND_STRUCTURES, {
                        filter: (structure) => (structure.structureType == STRUCTURE_PORTAL)
                    });
                }
                if (thisPortal) {
                    creep.travelTo(thisPortal, {
                        ignoreRoads: true
                    });
                } else if ((creep.pos.x == 0 || creep.pos.x == 49 || creep.pos.y == 0 || creep.pos.y == 49) && targetAttacker.room.name == creep.room.name) {
                    /*var xTarget = 0;
                    var yTarget = 0;
                    if (creep.pos.x == 0) {
                        xTarget = 2;
                        yTarget = creep.pos.y;
                    } else if (creep.pos.x == 49) {
                        xTarget = 47;
                        yTarget = creep.pos.y;
                    }
                    if (creep.pos.y == 0) {
                        yTarget = 2;
                        xTarget = creep.pos.x;
                    } else if (creep.pos.y == 49) {
                        yTarget = 47;
                        xTarget = creep.pos.x;
                    }

                    creep.moveTo(xTarget, yTarget);*/
                    creep.moveTo(targetAttacker.pos);
                } else {
                    /*if (creep.pos.inRangeTo(targetAttacker, 2)) {
                        creep.move(creep.pos.getDirectionTo(targetAttacker));
                    } else {*/
                    if (targetAttacker.room.name == creep.room.name) {
                        creep.travelTo(targetAttacker, {
                            maxRooms: 1,
                            ignoreRoads: true,
                            stuckValue: 1
                        });
                    } else {
                        creep.travelTo(targetAttacker, {
                            ignoreRoads: true,
                            stuckValue: 1
                        });
                    }
                    //}
                }

                if (creep.hits < creep.hitsMax - 400) {
                    creep.heal(creep);
                    creep.say("(=\u2716\u11BD\u2716=)", true);
                } else {

                    if (Game.time % 2 == 0) {
                        creep.say("(=\u25D5\u11BD\u25D5\u0E3A=)", true);
                    } else {
                        creep.say("(=\u229D\u11BD\u229D=)", true);
                    }

                    var hurtAlly = creep.pos.findInRange(FIND_CREEPS, 3, {
                        filter: (thisCreep) => thisCreep.hits < thisCreep.hitsMax - 600 && thisCreep.id != targetAttacker.id && (thisCreep.owner.username == "Montblanc" || Memory.whiteList.includes(thisCreep.owner.username))
                    });
                    var healedAlly = false
                    if (hurtAlly.length > 0) {
                        hurtAlly.sort(healCompare);
                        if (creep.pos.getRangeTo(hurtAlly[0]) > 1) {
                            if (creep.rangedHeal(hurtAlly[0]) == OK) {
                                healedAlly = true;
                            }
                        } else {
                            if (creep.heal(hurtAlly[0]) == OK) {
                                healedAlly = true;
                            }
                        }
                    }

                    if (!healedAlly) {
                        if (creep.pos.getRangeTo(targetAttacker) > 1) {
                            creep.rangedHeal(targetAttacker);
                        } else {
                            creep.heal(targetAttacker);
                        }
                    }
                }
            } else {
                creep.memory.UnassignDelay++;
                if (creep.memory.UnassignDelay > 10) {
                    creep.memory.priority = 'targetlessHealer';
                }
                creep.heal(creep);
                if (Game.flags[creep.memory.homeRoom + "RallyHere"] && Game.flags[creep.memory.homeRoom + "RallyHere"].pos) {
                    creep.travelTo(Game.flags[creep.memory.homeRoom + "RallyHere"], {
                        ignoreRoads: true
                    });
                }
                var newTarget = creep.pos.findInRange(FIND_MY_CREEPS, 10, {
                    filter: (mCreep) => (mCreep.memory.priority == "assattacker")
                });
                if (newTarget.length) {
                    creep.memory.attackerID = newTarget[0].id;
                }
            }
        }
    }

};

function healCompare(a, b) {
    if (a.hits < b.hits)
        return -1;
    if (a.hits > b.hits)
        return 1;
    return 0;
}

module.exports = creep_asshealer;<|endoftext|>


<commit_before>function print(text) {
	var date = (new Date()).toString();

	var row = document.createElement("tr");
	row.innerHTML = "" + date + "	" + text + "	";

	var output = document.getElementById("output")
	output.appendChild(row);
}

function test() {
	var session = NinchatClient.newSession();

	function hello(user_id) {
		var header = {
			action:       "send_message",
			user_id:      user_id,
			message_type: "ninchat.com/text"
		};

		var payload = [
			JSON.stringify({"text": "hello me"})
		];

		session.send(header, payload);
	}

	session.onSessionEvent(function(header) {
		print("SESSION: " + JSON.stringify(header));
		print("BINARY: " + session.binarySupported());

		if (header.event === "session_created") {
			hello(header.user_id);
		}
	});

	session.onEvent(function(header, payload) {
		print("EVENT: " + JSON.stringify(header));

		for (var i = 0; i < payload.length; i++) {
			print("PAYLOAD: " + NinchatClient.stringifyFrame(payload[i]));
		}
	});

	session.onConnState(function(state) {
		print("STATE: " + state);
	});

	session.onConnActive(function(time) {
		print("ACTIVE: " + (new Date(time)).toString());
	});

	session.onLog(function(message) {
		print("LOG: " + message);
	});

	if (true) {
		// don't even try websocket
		session.setTransport("longpoll");
	}

	var params = {
		message_types: [
			"ninchat.com/info/*",
			"ninchat.com/link",
			"ninchat.com/notice",
			"ninchat.com/text"
		]
	};

	if (false) {
		// log in with an identity
		params.identity_type = "email";
		params.identity_name = "bob@example.invalid";
		params.identity_auth = "password goes here";
	} else if (false) {
		// log in with a user agent authentication token
		params.user_id = "user id goes here";
		params.user_auth = "secret token goes here";
	} else if (false) {
		// create a new user and associate a new identity to it
		params.identity_type_new = "email";
		params.identity_name_new = "bob@example.invalid";
		params.identity_auth_new = "password goes here";
	} else {
		// create a new user without an identity
	}

	session.setParams(params);
	session.open();

	if (false) {
		setTimeout(session.close, 15000);
	}
}
<commit_msg>test elaboration<commit_after>function print(text) {
	var date = (new Date()).toString();

	var row = document.createElement("tr");
	row.innerHTML = "" + date + "	" + text + "	";

	var output = document.getElementById("output")
	output.appendChild(row);

	row.scrollIntoView();
}

function test() {
	var session = NinchatClient.newSession();

	session.onSessionEvent(function(sessionHeader) {
		print("SESSION: " + JSON.stringify(sessionHeader));
		print("BINARY: " + session.binarySupported());

		var sendSequence = 1;

		var intervalId = setInterval(function() {
			var messageHeader = {
				action:       "send_message",
				user_id:      sessionHeader.user_id,
				message_type: "ninchat.com/text"
			};

			var messagePayload = [
				JSON.stringify({"text": "" + sendSequence})
			];

			session.send(messageHeader, messagePayload);

			if (sendSequence == 100) {
				clearInterval(intervalId);
			} else {
				sendSequence++;
			}
		}, 100);
	});

	var eventSequence = 2;
	var actionSequence = 1;
	var receiveSequence = [];
	var closing = false;

	session.onEvent(function(header, payload) {
		print("HEADER: " + JSON.stringify(header));

		if (header.event_id !== undefined) {
			if (header.event_id == (eventSequence++)) {
				print("EVENT: " + header.event_id);
			} else {
				print("EVENT OUT OF SEQUENCE: " + header.event_id);
			}
		}

		if (header.action_id !== undefined) {
			if (header.action_id == (actionSequence++)) {
				print("ACTION: " + header.action_id);
			} else {
				print("ACTION: " + header.action_id + " (out of sequence)");
			}
		}

		if (payload) {
			var msg = NinchatClient.stringifyFrame(payload[0]);
			var seq = parseInt(JSON.parse(msg).text);
			print("MESSAGE: " + msg);
			receiveSequence.push(seq);

			if (seq >= 100 && !closing) {
				closing = true;

				setTimeout(function() {
					session.close();

					var ok = true;

					for (var find = 1; find <= 100; find++) {
						var found = false;

						for (var i = 0; i < receiveSequence.length; i++) {
							if (receiveSequence[i] === find) {
								found = true;
								break;
							}
						}

						if (!found) {
							print("MISSING MESSAGE: " + find);
							ok = false;
						}
					}

					if (ok) {
						print("ALL MESSAGES RECEIVED");
					}
				}, 3000);
			}
		}
	});

	session.onConnState(function(state) {
		print("STATE: " + state);
	});

	if (false) {
		session.onConnActive(function(time) {
			print("ACTIVE: " + (new Date(time)).toString());
		});
	}

	session.onLog(function(message) {
		print("LOG: " + message);
	});

	if (false) {
		// don't even try websocket
		session.setTransport("longpoll");
	}

	var params = {
		message_types: [
			"ninchat.com/info/*",
			"ninchat.com/link",
			"ninchat.com/notice",
			"ninchat.com/text"
		]
	};

	if (false) {
		// log in with an identity
		params.identity_type = "email";
		params.identity_name = "bob@example.invalid";
		params.identity_auth = "password goes here";
	} else if (false) {
		// log in with a user agent authentication token
		params.user_id = "user id goes here";
		params.user_auth = "secret token goes here";
	} else if (false) {
		// create a new user and associate a new identity to it
		params.identity_type_new = "email";
		params.identity_name_new = "bob@example.invalid";
		params.identity_auth_new = "password goes here";
	} else {
		// create a new user without an identity
	}

	session.setParams(params);
	session.open();
}
<|endoftext|>


<commit_before>/** @jsx React.DOM */
/**
 * 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.
 */

var React = window.React;
var _ = window._;
var bows = window.bows;

var tidelineBlip = window.tideline.blip;
var chartDailyFactory = tidelineBlip.oneday;
var chartWeeklyFactory = tidelineBlip.twoweek;
var settingsFactory = tidelineBlip.settings;

var Chart = React.createClass({
  propTypes: {
    patientData: React.PropTypes.object,
    chartType: React.PropTypes.string,
    datetimeLocation: React.PropTypes.string,
    onDatetimeLocationChange: React.PropTypes.func,
    onSelectDataPoint: React.PropTypes.func,
    onShowMessageThread: React.PropTypes.func,
    onCreateMessage: React.PropTypes.func,
    onTransition: React.PropTypes.func,
    onReachedMostRecent: React.PropTypes.func,
    imagesEndpoint: React.PropTypes.string
  },

  log: bows('Chart'),

  chart: null,

  componentDidMount: function() {
    var data = this.props.patientData;
    var datetimeLocation = this.props.datetimeLocation;

    this.mountChart();
    this.initializeChart(data, datetimeLocation);
  },

  componentWillUnmount: function() {
    this.unmountChart();
  },

  componentDidUpdate: function() {
    if (this.chart.type !== this.props.chartType) {
      this.unmountChart();

      var data = this.props.patientData;
      var datetimeLocation = this.props.datetimeLocation;

      this.mountChart();
      this.initializeChart(data, datetimeLocation);
    }
  },

  render: function() {
    /* jshint ignore:start */
    return (

    );
    /* jshint ignore:end */
  },

  mountChart: function() {
    if (!this.chart) {
      this.log('Creating new charts; mounting daily chart.');
      var el = this.refs.chart.getDOMNode();
      var imagesBaseUrl = this.props.imagesEndpoint;

      var dailyChart = chartDailyFactory(this.refs.chart.getDOMNode(), {imagesBaseUrl: imagesBaseUrl}).setupPools();
      this.chart = dailyChart;
      this.dailyChart = dailyChart;
      var weeklyChart = chartWeeklyFactory(this.refs.chart.getDOMNode(), {imagesBaseUrl: imagesBaseUrl});
      this.weeklyChart = weeklyChart;
      var settings = settingsFactory(this.refs.chart.getDOMNode());
      this.settings = settings;
      this.bindEvents();
    }
    else {
      if (this.props.chartType === 'daily') {
        this.log('Mounting daily chart.');
        this.chart = this.dailyChart;
        this.bindEvents();
      }
      else if (this.props.chartType === 'weekly') {
        this.log('Mounting weekly chart.');
        this.chart = this.weeklyChart;
        this.bindEvents();
      }
      else if (this.props.chartType === 'settings') {
        this.log('Mounting settings.');
        this.chart = this.settings;
        this.bindEvents();
      }
    }
  },

  initializeChart: function(data, datetimeLocation) {
    var chart = this.chart;

    if (_.isEmpty(data)) {
      throw new Error('Cannot create new chart with no data');
    }

    chart.show().load(data, datetimeLocation);

    if (this.chart.type === 'daily') {
      if (datetimeLocation) {
        chart.locate(datetimeLocation);
      }
      else {
        chart.locate();
      }
    }
  },

  unmountChart: function() {
    if (this.chart) {
      this.log('Unmounting chart');
      this.chart.clear().hide();
    }
  },

  bindEvents: function() {
    if (this.props.onDatetimeLocationChange) {
      this.chart.emitter.on('navigated', this.props.onDatetimeLocationChange);
    }

    if (this.props.onSelectDataPoint) {
      this.chart.emitter.on('selectSMBG', this.props.onSelectDataPoint);
    }

    if (this.props.onTransition) {
      this.chart.emitter.on('inTransition', this.props.onTransition);
    }

    if (this.props.onReachedMostRecent) {
      this.chart.emitter.on('mostRecent', this.props.onReachedMostRecent);
    }

    if (this.props.onShowMessageThread) {
      this.chart.emitter.on('messageThread', this.props.onShowMessageThread);
    }

    if (this.props.onCreateMessage) {
      this.chart.emitter.on('createMessage', this.props.onCreateMessage);
    }
  },

  show: function() {
    return this.chart.show();
  },

  locate: function(datetime) {
    if (!datetime) {
      return this.chart.locate();
    }

    return this.chart.locate(datetime);
  },

  locateToMostRecent: function() {
    this.log('Navigated to most recent data.');
    var data = this.props.patientData;

    switch (this.chart.type) {
      case 'daily':
        this.chart.clear().locate();
        break;
      case 'weekly':
        this.chart.clear().load(this.props.patientData);
        break;
      case 'settings':
        return;
        break;
      default:
        throw new Error('Unknown chart type: ' + this.chart.type);
    }
  },

  panForward: function() {
    return this.chart.panForward();
  },

  panBack: function() {
    return this.chart.panBack();
  },

  getCurrentDay: function() {
    return this.chart.getCurrentDay();
  },

  showValues: function() {
    return this.chart.showValues();
  },

  hideValues: function() {
    return this.chart.hideValues();
  },

  createMessageThread: function(id) {
    return this.chart.createMessage(id);
  },

  closeMessageThread: function() {
    return this.chart.closeMessage();
  }
});

module.exports = Chart;<commit_msg>tideline needs to know about the whole message, not just the ID<commit_after>/** @jsx React.DOM */
/**
 * 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.
 */

var React = window.React;
var _ = window._;
var bows = window.bows;

var tidelineBlip = window.tideline.blip;
var chartDailyFactory = tidelineBlip.oneday;
var chartWeeklyFactory = tidelineBlip.twoweek;
var settingsFactory = tidelineBlip.settings;

var Chart = React.createClass({
  propTypes: {
    patientData: React.PropTypes.object,
    chartType: React.PropTypes.string,
    datetimeLocation: React.PropTypes.string,
    onDatetimeLocationChange: React.PropTypes.func,
    onSelectDataPoint: React.PropTypes.func,
    onShowMessageThread: React.PropTypes.func,
    onCreateMessage: React.PropTypes.func,
    onTransition: React.PropTypes.func,
    onReachedMostRecent: React.PropTypes.func,
    imagesEndpoint: React.PropTypes.string
  },

  log: bows('Chart'),

  chart: null,

  componentDidMount: function() {
    var data = this.props.patientData;
    var datetimeLocation = this.props.datetimeLocation;

    this.mountChart();
    this.initializeChart(data, datetimeLocation);
  },

  componentWillUnmount: function() {
    this.unmountChart();
  },

  componentDidUpdate: function() {
    if (this.chart.type !== this.props.chartType) {
      this.unmountChart();

      var data = this.props.patientData;
      var datetimeLocation = this.props.datetimeLocation;

      this.mountChart();
      this.initializeChart(data, datetimeLocation);
    }
  },

  render: function() {
    /* jshint ignore:start */
    return (

    );
    /* jshint ignore:end */
  },

  mountChart: function() {
    if (!this.chart) {
      this.log('Creating new charts; mounting daily chart.');
      var el = this.refs.chart.getDOMNode();
      var imagesBaseUrl = this.props.imagesEndpoint;

      var dailyChart = chartDailyFactory(this.refs.chart.getDOMNode(), {imagesBaseUrl: imagesBaseUrl}).setupPools();
      this.chart = dailyChart;
      this.dailyChart = dailyChart;
      var weeklyChart = chartWeeklyFactory(this.refs.chart.getDOMNode(), {imagesBaseUrl: imagesBaseUrl});
      this.weeklyChart = weeklyChart;
      var settings = settingsFactory(this.refs.chart.getDOMNode());
      this.settings = settings;
      this.bindEvents();
    }
    else {
      if (this.props.chartType === 'daily') {
        this.log('Mounting daily chart.');
        this.chart = this.dailyChart;
        this.bindEvents();
      }
      else if (this.props.chartType === 'weekly') {
        this.log('Mounting weekly chart.');
        this.chart = this.weeklyChart;
        this.bindEvents();
      }
      else if (this.props.chartType === 'settings') {
        this.log('Mounting settings.');
        this.chart = this.settings;
        this.bindEvents();
      }
    }
  },

  initializeChart: function(data, datetimeLocation) {
    var chart = this.chart;

    if (_.isEmpty(data)) {
      throw new Error('Cannot create new chart with no data');
    }

    chart.show().load(data, datetimeLocation);

    if (this.chart.type === 'daily') {
      if (datetimeLocation) {
        chart.locate(datetimeLocation);
      }
      else {
        chart.locate();
      }
    }
  },

  unmountChart: function() {
    if (this.chart) {
      this.log('Unmounting chart');
      this.chart.clear().hide();
    }
  },

  bindEvents: function() {
    if (this.props.onDatetimeLocationChange) {
      this.chart.emitter.on('navigated', this.props.onDatetimeLocationChange);
    }

    if (this.props.onSelectDataPoint) {
      this.chart.emitter.on('selectSMBG', this.props.onSelectDataPoint);
    }

    if (this.props.onTransition) {
      this.chart.emitter.on('inTransition', this.props.onTransition);
    }

    if (this.props.onReachedMostRecent) {
      this.chart.emitter.on('mostRecent', this.props.onReachedMostRecent);
    }

    if (this.props.onShowMessageThread) {
      this.chart.emitter.on('messageThread', this.props.onShowMessageThread);
    }

    if (this.props.onCreateMessage) {
      this.chart.emitter.on('createMessage', this.props.onCreateMessage);
    }
  },

  show: function() {
    return this.chart.show();
  },

  locate: function(datetime) {
    if (!datetime) {
      return this.chart.locate();
    }

    return this.chart.locate(datetime);
  },

  locateToMostRecent: function() {
    this.log('Navigated to most recent data.');
    var data = this.props.patientData;

    switch (this.chart.type) {
      case 'daily':
        this.chart.clear().locate();
        break;
      case 'weekly':
        this.chart.clear().load(this.props.patientData);
        break;
      case 'settings':
        return;
        break;
      default:
        throw new Error('Unknown chart type: ' + this.chart.type);
    }
  },

  panForward: function() {
    return this.chart.panForward();
  },

  panBack: function() {
    return this.chart.panBack();
  },

  getCurrentDay: function() {
    return this.chart.getCurrentDay();
  },

  showValues: function() {
    return this.chart.showValues();
  },

  hideValues: function() {
    return this.chart.hideValues();
  },

  createMessageThread: function(message) {
    return this.chart.createMessage(message);
  },

  closeMessageThread: function() {
    return this.chart.closeMessage();
  }
});

module.exports = Chart;<|endoftext|>