<commit_before>import {BarTrack} from './BarTrack';
import {scaleLinear, scaleOrdinal, schemeCategory10} from 'd3-scale';
import {range} from 'd3-array';
import {colorToHex} from './utils';

export class StackedBarTrack extends BarTrack {
  constructor(scene, dataConfig, handleTilesetInfoReceived, option, animate, onValueScaleChanged) {
    super(scene, dataConfig, handleTilesetInfoReceived, option, animate, onValueScaleChanged);
  }

  initTile(tile) {
    this.renderTile(tile);
  }

  renderTile(tile) {
    const graphics = tile.graphics;
    tile.drawnAtScale = this._xScale.copy();

    // we're setting the start of the tile to the current zoom level
    const {tileX, tileWidth} = this.getTilePosAndDimensions(tile.tileData.zoomLevel,
      tile.tileData.tilePos, this.tilesetInfo.tile_size);

    const shapeX = tile.tileData.shape[0]; // number of different nucleotides in each bar
    const shapeY = tile.tileData.shape[1]; // number of bars
    let flattenedArray = tile.tileData.dense;

    // if any data is negative, switch to exponential scale
    if (flattenedArray.filter((a) => a < 0).length > 0 && this.options.valueScaling === 'linear') {
      console.warn('Negative values present in data. Defaulting to exponential scale.');
      this.options.valueScaling = 'exponential';
      // todo does anything meaningful even happen here
    }

    // un-flatten data into matrix of tile.tileData.shape[0] x tile.tileData.shape[1]
    // first array in the matrix will be [flattenedArray[0], flattenedArray[256], flattenedArray[512], etc.]
    // because of how flattenedArray comes back from the server.
    const matrix = [];
    for (let i = 0; i < shapeX; i++) {//6
      for (let j = 0; j < shapeY; j++) {//256;
        let singleBar;
        (matrix[j] === undefined) ? singleBar = [] : singleBar = matrix[j];
        singleBar.push(flattenedArray[(shapeY * i) + j]);
        matrix[j] = singleBar;
      }
    }

    if (this.options.scaledHeight === true) {

      // find max height of bars for scaling in the track
      let positiveMax = 0;
      let negativeMax = 0;
      for (let i = 0; i < matrix.length; i++) {
        const temp = matrix[i];

        // find total heights of each positive column and each negative column
        // and compare to highest overall values above
        const localPositiveMax = temp.filter((a) => a >= 0).reduce((a, b) => a + b, 0);
        (localPositiveMax > positiveMax) ? positiveMax = localPositiveMax : positiveMax;
        const localNegativeMax = Math.abs(temp.filter((a) => a < 0).reduce((a, b) => a + b, 0));
        (localNegativeMax > negativeMax) ? negativeMax = localNegativeMax : negativeMax;

      }
      this.drawVerticalBars(graphics, matrix, tileX, tileWidth, positiveMax, negativeMax);
    }
    else {
      // normalize each array in matrix
      for (let i = 0; i < matrix.length; i++) {
        const temp = matrix[i];
        const barValuesSum = temp.reduce((a, b) => a + b, 0);
        matrix[i] = temp.map((a) => a / barValuesSum);
      }
      this.drawNormalizedBars(graphics, matrix, tileX, tileWidth);
    }
  }

  /**
   * Draws graph using normalized values.
   *
   * @param graphics PIXI.Graphics instance
   * @param matrix 2d array of numbers representing nucleotides
   * @param tileX starting position of tile
   * @param tileWidth pre-scaled width of tile
   * @param positiveMax the height of the tallest bar in the positive part of the graph
   * @param negativeMax the height of the tallest bar in the negative part of the graph
   */
  drawVerticalBars(graphics, matrix, tileX, tileWidth, positiveMax, negativeMax) {
    graphics.clear();
    const trackHeight = this.dimensions[1];

    // get amount of trackHeight reserved for positive and for negative
    const unscaledHeight = positiveMax + negativeMax;
    const positiveTrackHeight = (positiveMax * trackHeight) / unscaledHeight;
    const negativeTrackHeight = (negativeMax * trackHeight) / unscaledHeight;

    const colorScale = scaleOrdinal()
      .range(this.options.colorScale)
      .domain(range(this.options.colorScale.length))
      || scaleOrdinal(schemeCategory10);
    const valueToPixels = scaleLinear()
      .domain([0, positiveMax])
      .range([0, trackHeight]);
    let prevStackedBarHeight = 0;

    for (let j = 0; j < matrix.length; j++) { // jth vertical bar in the graph
      const x = this._xScale(tileX + (j * tileWidth / this.tilesetInfo.tile_size));
      const width = this._xScale(tileX + (tileWidth / this.tilesetInfo.tile_size)) - this._xScale(tileX);

      // sorted from largest to smallest
      // we're grouping values along with their index in the column
      const positiveValsSorted = matrix[j].map((x,i) => [x,i]).filter((a) => a[0] >= 0).sort((a, b) => a[0] - b[0]);

      for (let i = 0; i < positiveValsSorted.length; i++) {
        const height = valueToPixels(positiveValsSorted[i][0]);
        const y = (trackHeight - negativeTrackHeight) - (prevStackedBarHeight + height);
        graphics.beginFill(colorToHex(colorScale(positiveValsSorted[i][1])));
        graphics.drawRect(x, y, width, height);
        prevStackedBarHeight = prevStackedBarHeight + height;
      }
      prevStackedBarHeight = 0;
    }

    for (let j = 0; j < matrix.length; j++) { // jth vertical bar in the graph
      const x = this._xScale(tileX + (j * tileWidth / this.tilesetInfo.tile_size));
      const width = this._xScale(tileX + (tileWidth / this.tilesetInfo.tile_size)) - this._xScale(tileX);
      // sorted from largest to smallest
      // we're grouping values along with their index in the column
      const negativeValsSorted = matrix[j].map((x,i) => [x,i]).filter((a) => a[0] < 0).sort((a, b) => a[0] - b[0]);

      for (let i = 0; i < negativeValsSorted.length; i++) {
        const height = valueToPixels(negativeValsSorted[i][0]);
        const y = positiveTrackHeight - (prevStackedBarHeight + height);
        graphics.beginFill(colorToHex(colorScale(negativeValsSorted[i][1])));
        graphics.drawRect(x, y, width, height);
        prevStackedBarHeight = prevStackedBarHeight - height;
      }
      prevStackedBarHeight = 0;
    }
  }

  /**
   * Draws graph using normalized values.
   *
   * @param graphics PIXI.Graphics instance
   * @param matrix 2d array of numbers representing nucleotides
   * @param tileX starting position of tile
   * @param tileWidth pre-scaled width of tile
   */
  drawNormalizedBars(graphics, matrix, tileX, tileWidth) {
    graphics.clear();
    const trackHeight = this.dimensions[1];
    const colorScale = scaleOrdinal(schemeCategory10);
    const valueToPixels = scaleLinear()
      .domain([0, 1])
      .range([0, trackHeight]);
    let prevStackedBarHeight = 0;

    for (let j = 0; j < matrix.length; j++) { // jth vertical bar in the graph
      const x = this._xScale(tileX + (j * tileWidth / this.tilesetInfo.tile_size));
      const width = this._xScale(tileX + (tileWidth / this.tilesetInfo.tile_size)) - this._xScale(tileX);

      // mapping each value to its original color. color: value
      const rowWithOriginalIndices = {};
      for (let i = 0; i < matrix[j].length; i++) {
        rowWithOriginalIndices[colorToHex(colorScale(i))] = matrix[j][i];
      }

      const sorted = matrix[j].sort((a, b) => {
        return b - a;
      });
      for (let i = 0; i < sorted.length; i++) {
        const y = this.position[0] + (prevStackedBarHeight * trackHeight);
        const height = valueToPixels(sorted[i]);
        for (let k in rowWithOriginalIndices) {
          if (rowWithOriginalIndices[k] !== null
            && rowWithOriginalIndices[k] === sorted[i]) {
            graphics.beginFill(k, 1);
          }
        }
        graphics.drawRect(x, y, width, height);
        prevStackedBarHeight = prevStackedBarHeight + sorted[i];
      }
      prevStackedBarHeight = 0;
    }
  }

  draw() {
    super.draw();
  }
}

export default StackedBarTrack;
<commit_msg>Massive ESLintify<commit_after>import { range } from 'd3-array';
import { scaleLinear, scaleOrdinal, schemeCategory10 } from 'd3-scale';

import BarTrack from './BarTrack';

import { colorToHex } from './utils';

export default class StackedBarTrack extends BarTrack {
  initTile(tile) {
    this.renderTile(tile);
  }

  renderTile(tile) {
    const graphics = tile.graphics;
    tile.drawnAtScale = this._xScale.copy();

    // we're setting the start of the tile to the current zoom level
    const { tileX, tileWidth } = this.getTilePosAndDimensions(
      tile.tileData.zoomLevel,
      tile.tileData.tilePos,
      this.tilesetInfo.tile_size
    );

    // number of different nucleotides in each bar
    const shapeX = tile.tileData.shape[0];
    // number of bars
    const shapeY = tile.tileData.shape[1];
    const flattenedArray = tile.tileData.dense;

    // if any data is negative, switch to exponential scale
    if (
      flattenedArray.filter(a => a < 0).length > 0 &&
      this.options.valueScaling === 'linear'
    ) {
      console.warn(
        'Negative values present in data. Defaulting to exponential scale.'
      );
      this.options.valueScaling = 'exponential';
      // todo does anything meaningful even happen here
    }

    // un-flatten data into matrix of:
    //  tile.tileData.shape[0] x tile.tileData.shape[1]
    // first array in the matrix will be
    //  [flattenedArray[0], flattenedArray[256], flattenedArray[512], etc.]
    // because of how flattenedArray comes back from the server.
    const matrix = [];
    for (let i = 0; i < shapeX; i++) {  // 6
      for (let j = 0; j < shapeY; j++) {  // 256
        const singleBar = matrix[j] === undefined ? [] : matrix[j];
        singleBar.push(flattenedArray[(shapeY * i) + j]);
        matrix[j] = singleBar;
      }
    }

    if (this.options.scaledHeight === true) {
      // find max height of bars for scaling in the track
      let positiveMax = 0;
      let negativeMax = 0;
      for (let i = 0; i < matrix.length; i++) {
        const temp = matrix[i];

        // find total heights of each positive column and each negative column
        // and compare to highest overall values above
        const localPositiveMax = temp
          .filter(a => a >= 0)
          .reduce((a, b) => a + b, 0);
        positiveMax = localPositiveMax > positiveMax
          ? localPositiveMax
          : positiveMax;
        const localNegativeMax = Math.abs(
          temp.filter(a => a < 0).reduce((a, b) => a + b, 0)
        );
        negativeMax = localNegativeMax > negativeMax
          ? localNegativeMax
          : negativeMax;
      }
      this.drawVerticalBars(
        graphics, matrix, tileX, tileWidth, positiveMax, negativeMax
      );
    } else {
      // normalize each array in matrix
      for (let i = 0; i < matrix.length; i++) {
        const temp = matrix[i];
        const barValuesSum = temp.reduce((a, b) => a + b, 0);
        matrix[i] = temp.map(a => a / barValuesSum);
      }
      this.drawNormalizedBars(graphics, matrix, tileX, tileWidth);
    }
  }

  /**
   * Draws graph using normalized values.
   * @param graphics PIXI.Graphics instance
   * @param matrix 2d array of numbers representing nucleotides
   * @param tileX starting position of tile
   * @param tileWidth pre-scaled width of tile
   * @param positiveMax the height of the tallest bar in the positive part of
   *   the graph
   * @param negativeMax the height of the tallest bar in the negative part of
   *   the graph
   */
  drawVerticalBars(
    graphics, matrix, tileX, tileWidth, positiveMax, negativeMax
  ) {
    graphics.clear();
    const trackHeight = this.dimensions[1];

    // get amount of trackHeight reserved for positive and for negative
    const unscaledHeight = positiveMax + negativeMax;
    const positiveTrackHeight = (positiveMax * trackHeight) / unscaledHeight;
    const negativeTrackHeight = (negativeMax * trackHeight) / unscaledHeight;

    const colorScale = scaleOrdinal()
      .range(this.options.colorScale)
      .domain(range(this.options.colorScale.length))
      || scaleOrdinal(schemeCategory10);
    const valueToPixels = scaleLinear()
      .domain([0, positiveMax])
      .range([0, trackHeight]);
    let prevStackedBarHeight = 0;

    for (let j = 0; j < matrix.length; j++) { // jth vertical bar in the graph
      const x = this._xScale(
        tileX + (j * tileWidth / this.tilesetInfo.tile_size)
      );
      const width = this._xScale(
        tileX + (tileWidth / this.tilesetInfo.tile_size)
      ) - this._xScale(tileX);

      // sorted from largest to smallest
      // we're grouping values along with their index in the column
      const positiveValsSorted = matrix[j]
        .map((_x, i) => [_x, i])
        .filter(a => a[0] >= 0)
        .sort((a, b) => a[0] - b[0]);

      for (let i = 0; i < positiveValsSorted.length; i++) {
        const height = valueToPixels(positiveValsSorted[i][0]);
        const y = (
          (trackHeight - negativeTrackHeight)
          - (prevStackedBarHeight + height)
        );
        graphics.beginFill(colorToHex(colorScale(positiveValsSorted[i][1])));
        graphics.drawRect(x, y, width, height);
        prevStackedBarHeight += height;
      }
      prevStackedBarHeight = 0;
    }

    for (let j = 0; j < matrix.length; j++) { // jth vertical bar in the graph
      const x = this._xScale(
        tileX + (j * tileWidth / this.tilesetInfo.tile_size)
      );
      const width = this._xScale(
        tileX + (tileWidth / this.tilesetInfo.tile_size)
      ) - this._xScale(tileX);
      // sorted from largest to smallest
      // we're grouping values along with their index in the column
      const negativeValsSorted = matrix[j]
        .map((_x, i) => [_x, i])
        .filter(a => a[0] < 0)
        .sort((a, b) => a[0] - b[0]);

      for (let i = 0; i < negativeValsSorted.length; i++) {
        const height = valueToPixels(negativeValsSorted[i][0]);
        const y = positiveTrackHeight - (prevStackedBarHeight + height);
        graphics.beginFill(colorToHex(colorScale(negativeValsSorted[i][1])));
        graphics.drawRect(x, y, width, height);
        prevStackedBarHeight -= height;
      }
      prevStackedBarHeight = 0;
    }
  }

  /**
   * Draws graph using normalized values.
   *
   * @param graphics PIXI.Graphics instance
   * @param matrix 2d array of numbers representing nucleotides
   * @param tileX starting position of tile
   * @param tileWidth pre-scaled width of tile
   */
  drawNormalizedBars(graphics, matrix, tileX, tileWidth) {
    graphics.clear();
    const trackHeight = this.dimensions[1];
    const colorScale = scaleOrdinal(schemeCategory10);
    const valueToPixels = scaleLinear()
      .domain([0, 1])
      .range([0, trackHeight]);
    let prevStackedBarHeight = 0;

    for (let j = 0; j < matrix.length; j++) { // jth vertical bar in the graph
      const x = this._xScale(
        tileX + (j * tileWidth / this.tilesetInfo.tile_size)
      );
      const width = this._xScale(
        tileX + (tileWidth / this.tilesetInfo.tile_size)
      ) - this._xScale(tileX);

      // mapping each value to its original color. color: value
      const rowWithOriginalIndices = {};
      for (let i = 0; i < matrix[j].length; i++) {
        rowWithOriginalIndices[colorToHex(colorScale(i))] = matrix[j][i];
      }

      const sorted = matrix[j].sort((a, b) => b - a);
      for (let i = 0; i < sorted.length; i++) {
        const y = this.position[0] + (prevStackedBarHeight * trackHeight);
        const height = valueToPixels(sorted[i]);
        for (let k in rowWithOriginalIndices) {
          if (rowWithOriginalIndices[k] !== null
            && rowWithOriginalIndices[k] === sorted[i]) {
            graphics.beginFill(k, 1);
          }
        }
        graphics.drawRect(x, y, width, height);
        prevStackedBarHeight += sorted[i];
      }
      prevStackedBarHeight = 0;
    }
  }
}
<|endoftext|>


<commit_before>import React from 'react';

import SPELLS from 'common/SPELLS';
import calculateEffectiveHealing from 'parser/core/calculateEffectiveHealing';
import Analyzer, { SELECTED_PLAYER } from 'parser/core/Analyzer';
import Statistic from 'interface/statistics/Statistic';
import STATISTIC_ORDER from 'interface/others/STATISTIC_ORDER';
import STATISTIC_CATEGORY from 'interface/others/STATISTIC_CATEGORY';
import ItemDamageDone from 'interface/ItemDamageDone';
import ItemHealingDone from 'interface/ItemHealingDone';
import Events from 'parser/core/Events';

import BoringSpellValueText from 'interface/statistics/components/BoringSpellValueText';

class HarmDenial extends Analyzer {

  healingIncrease = 0;

  healingBoost = 0;
  bonusDamage = 0;

  /**
   * Expel harm healing is boosted by x%
   */
  constructor(...args) {
    super(...args);
    this.active = false;//FIXME actually check if they have the conduit
    if (!this.active) {
      return;
    }

    this.healingBoost = .2;

    this.addEventListener(Events.heal.by(SELECTED_PLAYER).spell(SPELLS.EXPEL_HARM), this.extraHealing);
  }

  extraHealing(event) {
    const bonusHealing = calculateEffectiveHealing(event, this.healingBoost) || 0;
    this.healingIncrease += bonusHealing;
    this.bonusDamage += bonusHealing * .1;
  }

  statistic() {
    return (
      <Statistic
        position={STATISTIC_ORDER.OPTIONAL(13)}
        size="flexible"
        category={STATISTIC_CATEGORY.COVENANTS}
      >
        <BoringSpellValueText spell={SPELLS.HARM_DENIAL}>
          <ItemDamageDone amount={this.bonusDamage} />

          <ItemHealingDone amount={this.healingIncrease} />
        </BoringSpellValueText>
      </Statistic>
    );
  }
}

export default HarmDenial;<commit_msg>Update HarmDenial.js<commit_after>import React from 'react';

import SPELLS from 'common/SPELLS';
import calculateEffectiveHealing from 'parser/core/calculateEffectiveHealing';
import Analyzer, { SELECTED_PLAYER } from 'parser/core/Analyzer';
import Statistic from 'interface/statistics/Statistic';
import STATISTIC_ORDER from 'interface/others/STATISTIC_ORDER';
import STATISTIC_CATEGORY from 'interface/others/STATISTIC_CATEGORY';
import ItemDamageDone from 'interface/ItemDamageDone';
import ItemHealingDone from 'interface/ItemHealingDone';
import Events from 'parser/core/Events';

import BoringSpellValueText from 'interface/statistics/components/BoringSpellValueText';

class HarmDenial extends Analyzer {

  healingIncrease = 0;

  healingBoost = 0;
  bonusDamage = 0;

  /**
   * Expel harm healing is boosted by x%
   */
  constructor(...args) {
    super(...args);
    this.active = false;//FIXME actually check if they have the conduit
    if (!this.active) {
      return;
    }

    this.healingBoost = .2;

    this.addEventListener(Events.heal.by(SELECTED_PLAYER).spell([SPELLS.EXPEL_HARM, SPELLS.EXPEL_HARM_TARGET_HEAL]), this.extraHealing);
  }

  extraHealing(event) {
    const bonusHealing = calculateEffectiveHealing(event, this.healingBoost) || 0;
    this.healingIncrease += bonusHealing;
    this.bonusDamage += bonusHealing * .1;
  }

  statistic() {
    return (
      <Statistic
        position={STATISTIC_ORDER.OPTIONAL(13)}
        size="flexible"
        category={STATISTIC_CATEGORY.COVENANTS}
      >
        <BoringSpellValueText spell={SPELLS.HARM_DENIAL}>
          <ItemDamageDone amount={this.bonusDamage} />

          <ItemHealingDone amount={this.healingIncrease} />
        </BoringSpellValueText>
      </Statistic>
    );
  }
}

export default HarmDenial;
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors'),
	Committee = mongoose.model('Committee'),
	User = mongoose.model('User'),
	_ = require('lodash');

/**
 * Create a Committee
 */
exports.create = function(req, res) {
	var committee = new Committee(req.body);
	committee.user = req.user;

	committee.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee);
		}
	});
};

/**
 * Show the current Committee
 */
exports.read = function(req, res) {
	res.jsonp(req.committee);
};

/**
 * Update a Committee
 */
exports.update = function(req, res) {
	var committee = req.committee ;

	committee = _.extend(committee , req.body);

	committee.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee);
		}
	});
};

/**
 * Delete an Committee
 */
exports.delete = function(req, res) {
	var committee = req.committee;

	committee.remove(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee);
		}
	});
};

/**
 * List of Committees
 */
exports.list = function(req, res) {
	Committee.find().sort('-created').populate('user', 'displayName').exec(function(err, committees) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committees);
		}
	});
};
/**
 * List of Committee Members
 */
exports.getMembers = function(req, res) {
	var committee = req.committee;

	User.find({'_id':{$in: committee.members}}).exec(function(err, members) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(members);
		}
	});
};

/**
 * Add Committee Member
 */
exports.addMember = function(req, res) {
	var userById = req.params.userId;
	var committeeById = req.committee._id;

	Committee.update({'_id': committeeById}, {$addToSet:{'members': userById}} ).exec(function(err, committee){
		if(err){
			return res.status(401).send({
				message: errorHandler.getErrorMessage(err)
			});
		}else{
			res.jsonp(committee[0]);
		}
	});
};

/**
 * Remove Committee Member
 */
exports.removeMember = function(req, res) {
	var committeeById = req.committee._id;
	var memberById = req.params.userId;

	console.log(committeeById);
	console.log(memberById);

	Committee.update({'_id':committeeById},{$pull:{'members': memberById}}).exec(function(err, committee) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee[0]);
		}
	});
};

/**
 * Get Committee Chair
 */
exports.getChair = function(req, res) {
	var chairById = req.committee.chair;
	User.find({'_id': chairById}).exec(function(err, chair) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(chair[0]);
		}
	});
};

/**
 * Remove Committee Chair
 */
exports.removeChair = function(req, res) {
	var committeeById = req.committee._id;
	var chairById = req.committee.chair;

	console.log(committeeById);
	console.log(chairById);

	Committee.update({'_id':committeeById},{'chair': ''}).exec(function(err, committee) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee[0]);
		}
	});
};

/**
 * Change Committee Chair
 */
exports.updateChair = function(req, res) {
	var committeeById = req.committee._id;
	var chairById = req.params.userId;

	console.log(committeeById);
	console.log(chairById);

	Committee.update({'_id':committeeById},{'chair': chairById}).exec(function(err, committee) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee[0]);
		}
	});
};

/**
 * Committee middleware
 */
exports.committeeByID = function(req, res, next, id) { Committee.findById(id).populate('user', 'displayName').exec(function(err, committee) {
		if (err) return next(err);
		if (! committee) return next(new Error('Failed to load Committee ' + id));
		req.committee = committee ;
		next();
	});
};

/**
 * Committee authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	if (req.committee.user.id !== req.user.id) {
		return res.status(403).send('User is not authorized');
	}
	next();
};<commit_msg>quick fix for getChair<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors'),
	Committee = mongoose.model('Committee'),
	User = mongoose.model('User'),
	_ = require('lodash');

/**
 * Create a Committee
 */
exports.create = function(req, res) {
	var committee = new Committee(req.body);
	committee.user = req.user;

	committee.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee);
		}
	});
};

/**
 * Show the current Committee
 */
exports.read = function(req, res) {
	res.jsonp(req.committee);
};

/**
 * Update a Committee
 */
exports.update = function(req, res) {
	var committee = req.committee ;

	committee = _.extend(committee , req.body);

	committee.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee);
		}
	});
};

/**
 * Delete an Committee
 */
exports.delete = function(req, res) {
	var committee = req.committee;

	committee.remove(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee);
		}
	});
};

/**
 * List of Committees
 */
exports.list = function(req, res) {
	Committee.find().sort('-created').populate('user', 'displayName').exec(function(err, committees) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committees);
		}
	});
};
/**
 * List of Committee Members
 */
exports.getMembers = function(req, res) {
	var committee = req.committee;

	User.find({'_id':{$in: committee.members}}).exec(function(err, members) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(members);
		}
	});
};

/**
 * Add Committee Member
 */
exports.addMember = function(req, res) {
	var userById = req.params.userId;
	var committeeById = req.committee._id;

	Committee.update({'_id': committeeById}, {$addToSet:{'members': userById}} ).exec(function(err, committee){
		if(err){
			return res.status(401).send({
				message: errorHandler.getErrorMessage(err)
			});
		}else{
			res.jsonp(committee[0]);
		}
	});
};

/**
 * Remove Committee Member
 */
exports.removeMember = function(req, res) {
	var committeeById = req.committee._id;
	var memberById = req.params.userId;

	console.log(committeeById);
	console.log(memberById);

	Committee.update({'_id':committeeById},{$pull:{'members': memberById}}).exec(function(err, committee) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee[0]);
		}
	});
};

/**
 * Get Committee Chair
 */
exports.getChair = function(req, res) {
	var chairById = req.committee.chair;
	User.find({'_id': chairById}).exec(function(err, chair) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(chair[0]);
		}
	});
};

/**
 * Remove Committee Chair
 */
exports.removeChair = function(req, res) {
	var committeeById = req.committee._id;
	var chairById = req.committee.chair;

	console.log(committeeById);
	console.log(chairById);

	Committee.update({'_id':committeeById},{'chair': ''}).exec(function(err, committee) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee[0]);
		}
	});
};

/**
 * Change Committee Chair
 */
exports.updateChair = function(req, res) {
	var committeeById = req.committee._id;
	var chairById = req.committee.chair;

	console.log(committeeById);
	console.log(chairById);

	Committee.update({'_id':committeeById},{'chair': chairById}).exec(function(err, committee) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(committee[0]);
		}
	});
};

/**
 * Committee middleware
 */
exports.committeeByID = function(req, res, next, id) { Committee.findById(id).populate('user', 'displayName').exec(function(err, committee) {
		if (err) return next(err);
		if (! committee) return next(new Error('Failed to load Committee ' + id));
		req.committee = committee ;
		next();
	});
};

/**
 * Committee authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
	if (req.committee.user.id !== req.user.id) {
		return res.status(403).send('User is not authorized');
	}
	next();
};<|endoftext|>


<commit_before>import m from 'mithril';
import _ from 'underscore';
import classNames from 'classnames';
import Browser from '../browser';

// The grid UI, including the pending chip (i.e. the chip to be placed), as well
// as all chips currently placed on the grid
var GridComponent = {};

GridComponent.oninit = function (vnode) {
  var game = vnode.attrs.game;
  var state = vnode.state;
  _.extend(state, {
    // Reset/initialize the entire state of the controller
    reset: function () {
      // The cached width of a single chip
      state.chipWidth = null;
      // Current CSS position of the pending chip
      state.pendingChipX = 0;
      state.pendingChipY = 0;
      // Booleans indicating when to transition the pending chip's movement in a
      // particular direction (for example, the pending chip should never
      // transition when resetting to its initial position after placing a chip)
      state.transitionPendingChipX = false;
      state.transitionPendingChipY = false;
      // The current CSS position of the column where the user's cursor/finger
      // last clicked/touched
      state.lastVisitedColumnX = 0;
    },
    // Get the CSS translate string for the given coordinate map
    getTranslate: function (coords) {
      return 'translate(' + coords.x + 'px,' + coords.y + 'px)';
    },
    // Retrieve the constant width of a single chip
    getChipWidth: function () {
      // Cache the width to eliminate successive superfluous reflows
      if (!state.chipWidth) {
        var gridElem = document.getElementById('grid');
        state.chipWidth = gridElem.offsetWidth / game.grid.columnCount;
      }
      return state.chipWidth;
    },
    // Get the index of the last visited column (the column where the cursor was
    // last at or where the last chip was dropped)
    getLastVisitedColumnIndex: function (mouseEvent) {
      var chipWidth = state.getChipWidth();
      return Math.max(0, Math.floor((mouseEvent.pageX - mouseEvent.currentTarget.offsetLeft) / chipWidth));
    },
    // Run the given callback when the next (and only the very next) pending
    // chip transition finishes
    waitForPendingChipTransitionEnd: function (callback) {
      game.off('pending-chip:transition-end');
      game.once('pending-chip:transition-end', callback);
    },
    // Horizontally align the pending chip with the specified column
    alignPendingChipWithColumn: function (args) {
      // The last visited column is the grid column nearest to the cursor at
      // any given instant; keep track of the column's X position so the next
      // pending chip can instantaneously appear there
      var newLastVisitedColumnX = state.getChipWidth() * args.column;
      if (newLastVisitedColumnX !== state.lastVisitedColumnX) {
        state.lastVisitedColumnX = newLastVisitedColumnX;
        state.pendingChipX = state.lastVisitedColumnX;
        state.pendingChipY = 0;
        state.transitionPendingChipX = true;
        state.transitionPendingChipY = false;
        state.waitForPendingChipTransitionEnd(function () {
          state.transitionPendingChipX = false;
          // Allow the caller of alignPendingChipWithColumn() to provide an
          // arbitrary callback to run when the pending chip transition ends
          if (args.transitionEnd) {
            args.transitionEnd();
          }
        });
      }
    },
    // Align the pending chip with the column nearest to the user's cursor
    alignPendingChipViaPointer: function (mousemoveEvent) {
      if (game.pendingChip && game.currentPlayer.type === 'human' && !state.transitionPendingChipY) {
        state.alignPendingChipWithColumn({
          column: state.getLastVisitedColumnIndex(mousemoveEvent)
        });
      } else {
        mousemoveEvent.redraw = false;
      }
    },
    // Get the coordinates of the chip slot element at the given column/row
    getSlotCoords: function (args) {
      var chipWidth = state.getChipWidth();
      return {
        x: chipWidth * args.column,
        y: chipWidth * (game.grid.rowCount - args.row)
      };
    },
    // Place the pending chip into the specified column (or, if the chip is not
    // currently aligned with said column, do so first without placing it)
    placePendingChip: function (args) {
      var rowIndex = game.grid.getNextAvailableSlot({
        column: args.column
      });
      // Do not allow user to place chip in column that is already full
      if (rowIndex === null) {
        return;
      }
      var slotCoords = state.getSlotCoords({
        column: args.column,
        row: rowIndex
      });
      // If pending chip is not currently aligned with chosen column
      if (state.pendingChipX !== slotCoords.x) {
        // First align pending chip with column
        state.alignPendingChipWithColumn({
          column: args.column,
          // On the AI's turn, automatically place the chip after aligning it
          // with the specified column
          transitionEnd: function () {
            if (game.currentPlayer.type === 'ai') {
              game.currentPlayer.wait(function () {
                state.placePendingChip(args);
              });
            }
          }
        });
      } else {
        // Otherwise, chip is already aligned; drop chip into place on grid
        state.transitionPendingChipX = false;
        state.transitionPendingChipY = true;
        // Keep track of where chip was dropped
        state.lastVisitedColumnX = slotCoords.x;
        // Translate chip to the visual position on the grid corresponding to
        // the above column and row
        state.pendingChipX = slotCoords.x;
        state.pendingChipY = slotCoords.y;
        // Perform insertion on internal game grid once transition has ended
        state.finishPlacingPendingChip(args);
      }
      m.redraw();
    },
    // Place the pending chip into the column where the user clicked
    placePendingChipViaPointer: function (clickEvent) {
      if (game.pendingChip && game.currentPlayer.type === 'human' && !state.transitionPendingChipX && !state.transitionPendingChipY) {
        state.placePendingChip({
          column: state.getLastVisitedColumnIndex(clickEvent)
        });
      } else {
        clickEvent.redraw = false;
      }
    },
    // Actually insert the pending chip into the internal grid once the falling
    // transition has ended
    finishPlacingPendingChip: function (args) {
      state.waitForPendingChipTransitionEnd(function () {
        game.placePendingChip({column: args.column});
        state.transitionPendingChipX = false;
        state.transitionPendingChipY = false;
        // Reset position of pending chip to the space directly above the last
        // visited column
        state.pendingChipX = state.lastVisitedColumnX;
        state.pendingChipY = 0;
        m.redraw();
      });
    },
    // Initialize pending chip element when it's first created
    initializePendingChip: function (pendingChipVnode) {
      // Ensure that any unfinished pending chip event listeners (from
      // previous games) are unbound
      game.off('pending-chip:transition-end');
      // Listen for whenever a pending chip transition finishes
      var eventName = Browser.normalizeEventName('transitionend');
      pendingChipVnode.dom.addEventListener(eventName, function () {
        game.emit('pending-chip:transition-end');
      });
    }
  });
  // Place chip automatically when AI computes its next move on its turn
  game.on('ai-player:compute-next-move', function (aiPlayer, bestMove) {
    aiPlayer.wait(function () {
      state.placePendingChip({
        column: bestMove.column
      });
    });
  });
  // Reset controller state when game ends
  game.on('game:end', function () {
    state.reset();
  });
  // Reset controller state whenever controller is initialized
  state.reset();
};
GridComponent.view = function (vnode) {
  var state = vnode.state;
  var game = vnode.attrs.game;
  var grid = game.grid;
  return m('div#grid', {
    onmousemove: state.alignPendingChipViaPointer,
    onclick: state.placePendingChipViaPointer
  }, [
    // The chip that is about to be placed on the grid
    game.pendingChip ?
      m('div', {
        class: classNames(
          'chip',
          'pending',
          game.pendingChip.player.color,
           {'transition-x': state.transitionPendingChipX},
           {'transition-y': state.transitionPendingChipY}
        ),
        style: Browser.normalizeStyles({
          transform: state.getTranslate({
            x: state.pendingChipX,
            y: state.pendingChipY
          })
        }),
        oncreate: state.initializePendingChip
      }) : null,
    // The part of the grid containing both placed chips and empty chip slots
    m('div#grid-columns', _.times(grid.columnCount, function (c) {
      return m('div.grid-column', _.times(grid.rowCount, function (r) {
        if (grid.columns[c][r]) {
          // If this grid slot is occupied, display the corresponding chip
          var chip = grid.columns[c][r];
          return m('div.chip', {
            class: classNames(
              chip.player.color,
              {'winning': chip.winning}
            )
          });
        } else {
          // If this grid slot is empty, display an empty slot circle
          return m('div.empty-chip-slot', {
            key: 'empty-chip-slot-' + [c, r].join('-')
          });
        }
      }));
    }))
  ]);
};

export default GridComponent;
<commit_msg>Convert grid component to ES6 class<commit_after>import m from 'mithril';
import _ from 'underscore';
import classNames from 'classnames';
import Browser from '../browser';

// The grid UI, including the pending chip (i.e. the chip to be placed), as well
// as all chips currently placed on the grid
class GridComponent {

  oninit(vnode) {
    this.game = vnode.attrs.game;
    this.grid = this.game.grid;
    // Place chip automatically when AI computes its next move on its turn
    this.game.on('ai-player:compute-next-move', (aiPlayer, bestMove) => {
      aiPlayer.wait(() => {
        this.placePendingChip({
          column: bestMove.column
        });
      });
    });
    // Reset controller state when game ends
    this.game.on('game:end', () => this.reset());
    // Reset controller state whenever controller is initialized
    this.reset();
  }

  // Reset/initialize the entire state of the controller
  reset() {
    // The cached width of a single chip
    this.chipWidth = null;
    // Current CSS position of the pending chip
    this.pendingChipX = 0;
    this.pendingChipY = 0;
    // Booleans indicating when to transition the pending chip's movement in a
    // particular direction (for example, the pending chip should never
    // transition when resetting to its initial position after placing a chip)
    this.transitionPendingChipX = false;
    this.transitionPendingChipY = false;
    // The current CSS position of the column where the user's cursor/finger
    // last clicked/touched
    this.lastVisitedColumnX = 0;
  }

  // Get the CSS translate string for the given coordinate map
  getTranslate(coords) {
    return 'translate(' + coords.x + 'px,' + coords.y + 'px)';
  }

  // Retrieve the constant width of a single chip
  getChipWidth() {
    // Cache the width to eliminate successive superfluous reflows
    if (!this.chipWidth) {
      var gridElem = document.getElementById('grid');
      this.chipWidth = gridElem.offsetWidth / this.game.grid.columnCount;
    }
    return this.chipWidth;
  }

  // Get the index of the last visited column (the column where the cursor was
  // last at or where the last chip was dropped)
  getLastVisitedColumnIndex(mouseEvent) {
    var chipWidth = this.getChipWidth();
    return Math.max(0, Math.floor((mouseEvent.pageX - mouseEvent.currentTarget.offsetLeft) / chipWidth));
  }

  // Run the given callback when the next (and only the very next) pending
  // chip transition finishes
  waitForPendingChipTransitionEnd(callback) {
    this.game.off('pending-chip:transition-end');
    this.game.once('pending-chip:transition-end', callback);
  }

  // Horizontally align the pending chip with the specified column
  alignPendingChipWithColumn(args) {
    // The last visited column is the grid column nearest to the cursor at
    // any given instant; keep track of the column's X position so the next
    // pending chip can instantaneously appear there
    var newLastVisitedColumnX = this.getChipWidth() * args.column;
    if (newLastVisitedColumnX !== this.lastVisitedColumnX) {
      this.lastVisitedColumnX = newLastVisitedColumnX;
      this.pendingChipX = this.lastVisitedColumnX;
      this.pendingChipY = 0;
      this.transitionPendingChipX = true;
      this.transitionPendingChipY = false;
      this.waitForPendingChipTransitionEnd(() => {
        this.transitionPendingChipX = false;
        // Allow the caller of alignPendingChipWithColumn() to provide an
        // arbitrary callback to run when the pending chip transition ends
        if (args.transitionEnd) {
          args.transitionEnd();
        }
      });
    }
  }

  // Align the pending chip with the column nearest to the user's cursor
  alignPendingChipViaPointer(mousemoveEvent) {
    if (this.game.pendingChip && this.game.currentPlayer.type === 'human' && !this.transitionPendingChipY) {
      this.alignPendingChipWithColumn({
        column: this.getLastVisitedColumnIndex(mousemoveEvent)
      });
    } else {
      mousemoveEvent.redraw = false;
    }
  }

  // Get the coordinates of the chip slot element at the given column/row
  getSlotCoords(args) {
    var chipWidth = this.getChipWidth();
    return {
      x: chipWidth * args.column,
      y: chipWidth * (this.game.grid.rowCount - args.row)
    };
  }

  // Place the pending chip into the specified column (or, if the chip is not
  // currently aligned with said column, do so first without placing it)
  placePendingChip(args) {
    var rowIndex = this.game.grid.getNextAvailableSlot({
      column: args.column
    });
    // Do not allow user to place chip in column that is already full
    if (rowIndex === null) {
      return;
    }
    var slotCoords = this.getSlotCoords({
      column: args.column,
      row: rowIndex
    });
    // If pending chip is not currently aligned with chosen column
    if (this.pendingChipX !== slotCoords.x) {
      // First align pending chip with column
      this.alignPendingChipWithColumn({
        column: args.column,
        // On the AI's turn, automatically place the chip after aligning it
        // with the specified column
        transitionEnd: () => {
          if (this.game.currentPlayer.type === 'ai') {
            this.game.currentPlayer.wait(() => {
              this.placePendingChip(args);
            });
          }
        }
      });
    } else {
      // Otherwise, chip is already aligned; drop chip into place on grid
      this.transitionPendingChipX = false;
      this.transitionPendingChipY = true;
      // Keep track of where chip was dropped
      this.lastVisitedColumnX = slotCoords.x;
      // Translate chip to the visual position on the grid corresponding to
      // the above column and row
      this.pendingChipX = slotCoords.x;
      this.pendingChipY = slotCoords.y;
      // Perform insertion on internal game grid once transition has ended
      this.finishPlacingPendingChip(args);
    }
    m.redraw();
  }

  // Place the pending chip into the column where the user clicked
  placePendingChipViaPointer(clickEvent) {
    if (this.game.pendingChip && this.game.currentPlayer.type === 'human' && !this.transitionPendingChipX && !this.transitionPendingChipY) {
      this.placePendingChip({
        column: this.getLastVisitedColumnIndex(clickEvent)
      });
    } else {
      clickEvent.redraw = false;
    }
  }

  // Actually insert the pending chip into the internal grid once the falling
  // transition has ended
  finishPlacingPendingChip(args) {
    this.waitForPendingChipTransitionEnd(() => {
      this.game.placePendingChip({column: args.column});
      this.transitionPendingChipX = false;
      this.transitionPendingChipY = false;
      // Reset position of pending chip to the space directly above the last
      // visited column
      this.pendingChipX = this.lastVisitedColumnX;
      this.pendingChipY = 0;
      m.redraw();
    });
  }

  // Initialize pending chip element when it's first created
  initializePendingChip(vnode) {
    // Ensure that any unfinished pending chip event listeners (from
    // previous games) are unbound
    this.game.off('pending-chip:transition-end');
    // Listen for whenever a pending chip transition finishes
    var eventName = Browser.normalizeEventName('transitionend');
    vnode.dom.addEventListener(eventName, () => {
      this.game.emit('pending-chip:transition-end');
    });
  }

  view() {
    return m('div#grid', {
      onmousemove: (mousemoveEvent) => this.alignPendingChipViaPointer(mousemoveEvent),
      onclick: (clickEvent) => this.placePendingChipViaPointer(clickEvent)
    }, [
      // The chip that is about to be placed on the grid
      this.game.pendingChip ?
        m('div', {
          class: classNames(
            'chip',
            'pending',
            this.game.pendingChip.player.color,
             {'transition-x': this.transitionPendingChipX},
             {'transition-y': this.transitionPendingChipY}
          ),
          style: Browser.normalizeStyles({
            transform: this.getTranslate({
              x: this.pendingChipX,
              y: this.pendingChipY
            })
          }),
          oncreate: (vnode) => this.initializePendingChip(vnode)
        }) : null,
      // The part of the grid containing both placed chips and empty chip slots
      m('div#grid-columns', _.times(this.grid.columnCount, (c) => {
        return m('div.grid-column', _.times(this.grid.rowCount, (r) => {
          if (this.grid.columns[c][r]) {
            // If this grid slot is occupied, display the corresponding chip
            var chip = this.grid.columns[c][r];
            return m('div.chip', {
              class: classNames(
                chip.player.color,
                {'winning': chip.winning}
              )
            });
          } else {
            // If this grid slot is empty, display an empty slot circle
            return m('div.empty-chip-slot', {
              key: 'empty-chip-slot-' + [c, r].join('-')
            });
          }
        }));
      }))
    ]);
  }

}

export default GridComponent;
<|endoftext|>


<commit_before>'use strict';

console.log('**********************USING MOCK BACKEND**********************');

angular.module('confRegistrationWebApp')
  .run(function ($httpBackend, uuid) {

    $httpBackend.whenGET(/views\/.*/).passThrough();

    var registrations = {
      '012': [
        {
          'user': 'user-1',
          'answers': [
            {
              'block': 'block-2',
              'value': {
                firstName: 'Ron',
                lastName: 'Steve'
              }
            },
            {
              'block': 'block-4',
              'value': 'Man'
            },
            {
              'block': 'block-5',
              'value': 'Yes'
            },
            {
              'block': 'block-6',
              'value': 'No'
            },
            {
              'block': 'block-7',
              'value': 'Waffles'
            },
            {
              'block': 'block-8',
              'value': 'Burger'
            },
            {
              'block': 'block-9',
              'value': 'Steak'
            }
          ]
        },
        {
          'user': 'user-2',
          'answers': [
            {
              'block': 'block-2',
              'value': 'Jerry'
            },
            {
              'block': 'block-3',
              'value': 'Perdue'
            },
            {
              'block': 'block-4',
              'value': 'Man'
            },
            {
              'block': 'block-5',
              'value': 'Yes'
            },
            {
              'block': 'block-6',
              'value': 'Yes'
            },
            {
              'block': 'block-7',
              'value': 'Pancakes'
            },
            {
              'block': 'block-8',
              'value': 'Sandwich'
            },
            {
              'block': 'block-9',
              'value': 'Shrimp'
            }
          ]
        },
        {
          'user': 'user-3',
          'answers': [
            {
              'block': 'block-2',
              'value': 'Tom'
            },
            {
              'block': 'block-4',
              'value': 'Man'
            },
            {
              'block': 'block-5',
              'value': 'No'
            },
            {
              'block': 'block-6',
              'value': 'Yes'
            },
            {
              'block': 'block-7',
              'value': 'Omelettes'
            },
            {
              'block': 'block-8',
              'value': 'Soup'
            },
            {
              'block': 'block-9',
              'value': 'Lobster'
            }
          ]
        }
      ]
    };

    var conferences = [
      {
        'id': '012',
        'name': 'A Sweet Fall Retreat',
        'landingPage': {
          'blocks':[
            {
              'id': 'landingpage-1',
              'title': 'Location',
              'type': 'paragraphContent',
              'content': '123 Main St. Orlando, FL, 32828'
            },
            {
              'id': 'landingpage-2',
              'title': 'Registration Begins',
              'type': 'paragraphContent',
              'content': 'August 19, 2013 12:00 AM Eastern Time'
            },
            {
              'id': 'landingpage-2',
              'title': 'Registration Ends',
              'type': 'paragraphContent',
              'content': 'October 12, 2013 3:00 AM Eastern Time'
            },
            {
              'id': 'landingpage-2',
              'title': 'Fall Retreat Starts',
              'type': 'paragraphContent',
              'content': 'October 18, 2013 6:00 PM Eastern Time'
            },
            {
              'id': 'landingpage-2',
              'title': 'Fall Retreat Ends',
              'type': 'paragraphContent',
              'content': 'October 20, 2013 10:00 AM Eastern Time'
            },
            {
              'id': 'landingpage-2',
              'title': 'Contact Info',
              'type': 'paragraphContent',
              'content': 'John Smith <john.smith@example.com> 555-555-5555'
            }
          ]
        },
        'pages': [
          {
            'id': '1',
            'title': 'About You',
            'blocks': [
              {
                'id': 'block-1',
                'title': 'Important Information',
                'type': 'paragraphContent',
                'content': 'We are glad you are coming to Fall Retreat!'
              },
              {
                'id': 'block-2',
                'title': 'What\'s your name?',
                'required': true,
                'type': 'nameQuestion'
              },
              {
                'id': 'block-3',
                'title': 'What school do you currently attend?',
                'type': 'textQuestion'
              },
              {
                'id': 'block-4',
                'title': 'Man or Lady?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Man',
                  'Lady'
                ]
              }
            ]
          },
          {
            'id': '2',
            'title': 'Rides',
            'blocks': [
              {
                'id': 'block-1',
                'title': 'Ride Situation',
                'type': 'paragraphContent',
                'content': 'If you are driving, please give someone a ride.'
              },
              {
                'id': 'block-5',
                'title': 'Do you have a car?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Yes',
                  'No'
                ]
              },
              {
                'id': 'block-6',
                'title': 'Do you need a ride?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Yes',
                  'No'
                ]
              }
            ]
          },
          {
            'id': '3',
            'title': 'Food',
            'blocks': [
              {
                'id': 'block-7',
                'title': 'What do you want to eat for breakfast?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Pancakes',
                  'Waffles',
                  'Omelettes'
                ]
              },
              {
                'id': 'block-8',
                'title': 'What do you want to eat for lunch?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Sandwich',
                  'Soup',
                  'Burger'
                ]
              },
              {
                'id': 'block-9',
                'title': 'What do you want to eat for dinner?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Steak',
                  'Shrimp',
                  'Lobster'
                ]
              }
            ]
          }
        ]
      },
      {
        'id': '123',
        'name': 'Fall Retreat WOOO'
      },
      {
        'id': '234',
        'name': 'Fall Retreat!'
      },
      {
        'id': '345',
        'name': 'Yet Another Fall Retreat (YAFR)'
      },
      {
        'id': '456',
        'name': 'Fall Retreat Is Never Gonna Give You Up'
      }
    ];

    $httpBackend.whenGET('conferences').respond(function () {
      console.log(arguments);
      var headers = {};
      return [200, conferences, headers];
    });
    $httpBackend.whenPOST('conferences').respond(function (verb, url, data) {
      console.log(arguments);

      var conference = angular.extend(angular.fromJson(data), { id: uuid() });

      var headers = {
        'Location': '/conferences/' + conference.id
      };
      return [201, conference, headers];
    });
    $httpBackend.whenGET(/^conferences\/[-a-zA-Z0-9]+\/?$/).respond(function (verb, url) {
      console.log(arguments);

      var conferenceId = url.split('/')[1];

      var conference = _.find(conferences, function (conference) {
        return angular.equals(conference.id, conferenceId);
      });

      return [200, conference, {}];
    });
    $httpBackend.whenPUT(/^conferences\/[-a-zA-Z0-9]+\/?$/).respond(function (verb, url, data) {
      console.log(arguments);

      var conferenceId = url.split('/')[1];

      var conference = _.find(conferences, function (conference) {
        return angular.equals(conference.id, conferenceId);
      });

      angular.extend(conference, angular.fromJson(data));

      return [200, conference, {}];
    });

    $httpBackend.whenGET(/^conferences\/[-a-zA-Z0-9]+\/registrations\/?$/).respond(function (verb, url) {
      console.log(arguments);

      var conferenceId = url.split('/')[1];

      return [200, registrations[conferenceId], {}];
    });
    $httpBackend.whenPOST(/^conferences\/[-a-zA-Z0-9]+\/registrations\/?$/).respond(function (verb, url) {
      console.log(arguments);

      var conferenceId = url.split('/')[1];

      var registration = {
        id: uuid(),
        conference: conferenceId
      };

      var headers = {
        'Location': '/registrations/' + registration.id
      };
      return [201, registration, headers];
    });
    $httpBackend.whenGET(/^conferences\/[-a-zA-Z0-9]+\/registrations\/current\/?$/).respond(function () {
      console.log(arguments);

      return [404];
    });
    $httpBackend.whenGET(/^registrations\/[-a-zA-Z0-9]+\/?$/).respond(function () {
      console.log(arguments);

      console.log('Not Implemented');

      return [404];
    });

    /*
    angular.forEach(conferences, function (conference) {
      $httpBackend.whenGET('conferences/' + conference.id).respond(function () {
        console.log(arguments);

        var headers = {};
        return [200, conference, headers];
      });

      $httpBackend.whenGET('conferences/' + conference.id + '/registrations').respond(function () {
        console.log(arguments);

        var headers = {};
        return [200, registrations[conference.id], headers];
      });

      $httpBackend.whenPOST('conferences/' + conference.id + '/registrations').respond(function () {
        console.log(arguments);

        var registration = {
          id: '752bab92-e8bf-11e2-91e2-0800200c9a66',
          user: 'c8cfaf61-e8a8-11e2-91e2-0800200c9a66',
          answers: []
        };

        var headers = {
          location: 'registrations/' + registration.id
        };
        return [201, registrations[conference.id], headers];
      });

      $httpBackend.whenGET('conferences/' + conference.id + '/registrations/current').respond(function () {
        console.log(arguments);

        var headers = {};
        var regForConf = registrations[conference.id];
        var theReg = _.find(regForConf, function (registration) {
          return angular.equals(registration.user, 'user-1');
        });
        console.log(theReg);
        return [200, theReg, headers];
      });
    });
    */
  });
<commit_msg>Return empty array of answers when creating a registration<commit_after>'use strict';

console.log('**********************USING MOCK BACKEND**********************');

angular.module('confRegistrationWebApp')
  .run(function ($httpBackend, uuid) {

    $httpBackend.whenGET(/views\/.*/).passThrough();

    var registrations = {
      '012': [
        {
          'user': 'user-1',
          'answers': [
            {
              'block': 'block-2',
              'value': {
                firstName: 'Ron',
                lastName: 'Steve'
              }
            },
            {
              'block': 'block-4',
              'value': 'Man'
            },
            {
              'block': 'block-5',
              'value': 'Yes'
            },
            {
              'block': 'block-6',
              'value': 'No'
            },
            {
              'block': 'block-7',
              'value': 'Waffles'
            },
            {
              'block': 'block-8',
              'value': 'Burger'
            },
            {
              'block': 'block-9',
              'value': 'Steak'
            }
          ]
        },
        {
          'user': 'user-2',
          'answers': [
            {
              'block': 'block-2',
              'value': 'Jerry'
            },
            {
              'block': 'block-3',
              'value': 'Perdue'
            },
            {
              'block': 'block-4',
              'value': 'Man'
            },
            {
              'block': 'block-5',
              'value': 'Yes'
            },
            {
              'block': 'block-6',
              'value': 'Yes'
            },
            {
              'block': 'block-7',
              'value': 'Pancakes'
            },
            {
              'block': 'block-8',
              'value': 'Sandwich'
            },
            {
              'block': 'block-9',
              'value': 'Shrimp'
            }
          ]
        },
        {
          'user': 'user-3',
          'answers': [
            {
              'block': 'block-2',
              'value': 'Tom'
            },
            {
              'block': 'block-4',
              'value': 'Man'
            },
            {
              'block': 'block-5',
              'value': 'No'
            },
            {
              'block': 'block-6',
              'value': 'Yes'
            },
            {
              'block': 'block-7',
              'value': 'Omelettes'
            },
            {
              'block': 'block-8',
              'value': 'Soup'
            },
            {
              'block': 'block-9',
              'value': 'Lobster'
            }
          ]
        }
      ]
    };

    var conferences = [
      {
        'id': '012',
        'name': 'A Sweet Fall Retreat',
        'landingPage': {
          'blocks':[
            {
              'id': 'landingpage-1',
              'title': 'Location',
              'type': 'paragraphContent',
              'content': '123 Main St. Orlando, FL, 32828'
            },
            {
              'id': 'landingpage-2',
              'title': 'Registration Begins',
              'type': 'paragraphContent',
              'content': 'August 19, 2013 12:00 AM Eastern Time'
            },
            {
              'id': 'landingpage-2',
              'title': 'Registration Ends',
              'type': 'paragraphContent',
              'content': 'October 12, 2013 3:00 AM Eastern Time'
            },
            {
              'id': 'landingpage-2',
              'title': 'Fall Retreat Starts',
              'type': 'paragraphContent',
              'content': 'October 18, 2013 6:00 PM Eastern Time'
            },
            {
              'id': 'landingpage-2',
              'title': 'Fall Retreat Ends',
              'type': 'paragraphContent',
              'content': 'October 20, 2013 10:00 AM Eastern Time'
            },
            {
              'id': 'landingpage-2',
              'title': 'Contact Info',
              'type': 'paragraphContent',
              'content': 'John Smith <john.smith@example.com> 555-555-5555'
            }
          ]
        },
        'pages': [
          {
            'id': '1',
            'title': 'About You',
            'blocks': [
              {
                'id': 'block-1',
                'title': 'Important Information',
                'type': 'paragraphContent',
                'content': 'We are glad you are coming to Fall Retreat!'
              },
              {
                'id': 'block-2',
                'title': 'What\'s your name?',
                'required': true,
                'type': 'nameQuestion'
              },
              {
                'id': 'block-3',
                'title': 'What school do you currently attend?',
                'type': 'textQuestion'
              },
              {
                'id': 'block-4',
                'title': 'Man or Lady?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Man',
                  'Lady'
                ]
              }
            ]
          },
          {
            'id': '2',
            'title': 'Rides',
            'blocks': [
              {
                'id': 'block-1',
                'title': 'Ride Situation',
                'type': 'paragraphContent',
                'content': 'If you are driving, please give someone a ride.'
              },
              {
                'id': 'block-5',
                'title': 'Do you have a car?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Yes',
                  'No'
                ]
              },
              {
                'id': 'block-6',
                'title': 'Do you need a ride?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Yes',
                  'No'
                ]
              }
            ]
          },
          {
            'id': '3',
            'title': 'Food',
            'blocks': [
              {
                'id': 'block-7',
                'title': 'What do you want to eat for breakfast?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Pancakes',
                  'Waffles',
                  'Omelettes'
                ]
              },
              {
                'id': 'block-8',
                'title': 'What do you want to eat for lunch?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Sandwich',
                  'Soup',
                  'Burger'
                ]
              },
              {
                'id': 'block-9',
                'title': 'What do you want to eat for dinner?',
                'type': 'radioQuestion',
                'required': true,
                'choices': [
                  'Steak',
                  'Shrimp',
                  'Lobster'
                ]
              }
            ]
          }
        ]
      },
      {
        'id': '123',
        'name': 'Fall Retreat WOOO'
      },
      {
        'id': '234',
        'name': 'Fall Retreat!'
      },
      {
        'id': '345',
        'name': 'Yet Another Fall Retreat (YAFR)'
      },
      {
        'id': '456',
        'name': 'Fall Retreat Is Never Gonna Give You Up'
      }
    ];

    $httpBackend.whenGET('conferences').respond(function () {
      console.log(arguments);
      var headers = {};
      return [200, conferences, headers];
    });
    $httpBackend.whenPOST('conferences').respond(function (verb, url, data) {
      console.log(arguments);

      var conference = angular.extend(angular.fromJson(data), { id: uuid() });

      var headers = {
        'Location': '/conferences/' + conference.id
      };
      return [201, conference, headers];
    });
    $httpBackend.whenGET(/^conferences\/[-a-zA-Z0-9]+\/?$/).respond(function (verb, url) {
      console.log(arguments);

      var conferenceId = url.split('/')[1];

      var conference = _.find(conferences, function (conference) {
        return angular.equals(conference.id, conferenceId);
      });

      return [200, conference, {}];
    });
    $httpBackend.whenPUT(/^conferences\/[-a-zA-Z0-9]+\/?$/).respond(function (verb, url, data) {
      console.log(arguments);

      var conferenceId = url.split('/')[1];

      var conference = _.find(conferences, function (conference) {
        return angular.equals(conference.id, conferenceId);
      });

      angular.extend(conference, angular.fromJson(data));

      return [200, conference, {}];
    });

    $httpBackend.whenGET(/^conferences\/[-a-zA-Z0-9]+\/registrations\/?$/).respond(function (verb, url) {
      console.log(arguments);

      var conferenceId = url.split('/')[1];

      return [200, registrations[conferenceId], {}];
    });
    $httpBackend.whenPOST(/^conferences\/[-a-zA-Z0-9]+\/registrations\/?$/).respond(function (verb, url) {
      console.log(arguments);

      var conferenceId = url.split('/')[1];

      var registration = {
        id: uuid(),
        conference: conferenceId,
        answers: []
      };

      var headers = {
        'Location': '/registrations/' + registration.id
      };
      return [201, registration, headers];
    });
    $httpBackend.whenGET(/^conferences\/[-a-zA-Z0-9]+\/registrations\/current\/?$/).respond(function () {
      console.log(arguments);

      return [404];
    });
    $httpBackend.whenGET(/^registrations\/[-a-zA-Z0-9]+\/?$/).respond(function () {
      console.log(arguments);

      console.log('Not Implemented');

      return [404];
    });

    /*
    angular.forEach(conferences, function (conference) {
      $httpBackend.whenGET('conferences/' + conference.id).respond(function () {
        console.log(arguments);

        var headers = {};
        return [200, conference, headers];
      });

      $httpBackend.whenGET('conferences/' + conference.id + '/registrations').respond(function () {
        console.log(arguments);

        var headers = {};
        return [200, registrations[conference.id], headers];
      });

      $httpBackend.whenPOST('conferences/' + conference.id + '/registrations').respond(function () {
        console.log(arguments);

        var registration = {
          id: '752bab92-e8bf-11e2-91e2-0800200c9a66',
          user: 'c8cfaf61-e8a8-11e2-91e2-0800200c9a66',
          answers: []
        };

        var headers = {
          location: 'registrations/' + registration.id
        };
        return [201, registrations[conference.id], headers];
      });

      $httpBackend.whenGET('conferences/' + conference.id + '/registrations/current').respond(function () {
        console.log(arguments);

        var headers = {};
        var regForConf = registrations[conference.id];
        var theReg = _.find(regForConf, function (registration) {
          return angular.equals(registration.user, 'user-1');
        });
        console.log(theReg);
        return [200, theReg, headers];
      });
    });
    */
  });
<|endoftext|>


<commit_before>/**
 * Prepros
 * (c) Subash Pathak
 * sbshpthk@gmail.com
 * License: MIT
 */

/*jshint browser: true, node: true*/
/*global prepros, angular, _, $*/

prepros.factory('config', function ($http) {

    'use strict';

    var fs = require('fs-extra'),
        path = require('path'),
        os = require('os');

    //Base path
    var basePath = path.join(path.dirname(process.execPath), 'app');

    //Package.json file url
    var packageFileUrl = path.join(basePath, '../package.json');

    //Read package.json file and get data of app in prepros object
    var packageData = angular.fromJson(fs.readFileSync(packageFileUrl).toString());

    //We need package path because everything is relative to this file
    var packagePath = path.join(basePath, '..');

    //CachePath
    var cachePath = path.join(os.tmpdir(), 'PreprosCache');

    //Node modules required by the app
    var node_modules = packageData.dependencies;

    //App version
    var version = packageData.version;

    //App urls
    var online = {
        url: 'http://alphapixels.com/prepros',
        helpUrl: 'http://alphapixels.com/prepros/docs/',
        loveUrl: 'http://alphapixels.com/prepros#love',
        updateFileUrl: 'https://raw.github.com/sbspk/Prepros/master/package.json',
        githubUrl: 'http://github.com/sbspk/prepros',
        authorTwitter: 'http://twitter.com/sbspk',
        authorUrl: 'http://alphapixels.com'
    };

    //Ruby Executable
    var ruby = {
        path: path.join(packagePath, packageData.ruby.path),
        version: packageData.ruby.version
    };

    //Gems
    ruby.gems = {};
    for ( var gemKey in packageData.ruby.gems ) {

        if(packageData.ruby.gems.hasOwnProperty(gemKey)) {
            ruby.gems[gemKey] = {

                path: path.join(packagePath, packageData.ruby.gems[gemKey].path),
                version: packageData.ruby.gems[gemKey].version
            };
        }
    }

    //Read user config
    var userConfig = {};
    try {

        $.parseJSON(localStorage.PreprosConfig || '{}');

    } catch (e) {

        window.alert('Error Reading Configurations ! Reverting to defaults.');

        saveUserOptions(userConfig);
    }

    var defaultConfig = {
        cssPath: 'css',
        jsPath: 'js',
        htmlPath: 'html',
        jsMinPath: 'min',
        htmlExtension: '.html',
        enableSuccessNotifications: true,
        enableErrorNotifications: true,
        filterPatterns: '',
        useCustomRuby: false,
        customRubyPath: '',

        //Default Less Options
        less : {
            autoCompile: true,
            compress : false,
            lineNumbers: false,
            strictMath: true,
            strictUnits: true
        },

        //Default Sass options
        sass : {
            autoCompile : true,
            lineNumbers : false,
            unixNewlines: false,
            debug: false,
            compass : false,
            fullCompass: false,
            outputStyle : 'expanded' //compressed, nested, expanded, compact
        },

        //Default Stylus Options
        stylus : {
            autoCompile: true,
            lineNumbers : false,
            nib : false,
            compress : false
        },

        //Default Markdown Options
        markdown : {
            autoCompile: true,
            sanitize: false,
            gfm: true
        },

        //Default Coffeescript Options
        coffee: {
            autoCompile: true,
            bare: false,
            uglify: false
        },

        //Default javascript options
        javascript: {
            autoCompile: true,
            uglify: true
        },

        //Default Jade  Options
        jade: {
            autoCompile: true,
            pretty: true
        },

        //Default Haml Options
        haml: {
            autoCompile: true,
            format: 'html5', //xhtml, html5
            outputStyle: 'indented', //indented, ugly
            doubleQuotes: false
        },

        //Default Slim  Options
        slim: {
            autoCompile: true,
            pretty: true,
            indent: 'default', //default, four, tab
            fourSpaceIndent: true,
            format: ':html5' //:xhtml, :html4, :html5, :html
        }
    };

    //Fill in the undefined values from default configurations
    userConfig = _.defaults(userConfig, defaultConfig);

    for ( var configKey in userConfig ) {

        if(userConfig.hasOwnProperty(configKey) && typeof userConfig[configKey] === 'object') {

            userConfig[configKey] = _.defaults(userConfig[configKey], defaultConfig[configKey]);
        }
    }

    //Wrap user options in a function to prevent angular data sharing between services
    //If user config data is shared between files changing configuration of one file will affect another file
    function getUserOptions() {

        return $.parseJSON(angular.toJson(userConfig, false));

    }

    function saveUserOptions(options) {

        localStorage.setItem('PreprosConfig', angular.toJson(options));

        userConfig = $.parseJSON(angular.toJson(options));
    }

    function checkUpdate(success, fail){

        var opt = {method: 'get', url: online.updateFileUrl, cache: false};

        var checker = $http(opt);

        checker.success(function(data){

            if(config.version !== data.version) {

                success({
                    available: true,
                    version: data.version,
                    date: data.releaseDate
                });
            } else {
                success({
                    available: false,
                    version: version,
                    date: data.releaseDate
                });
            }
        });

        checker.error(function(data){

            if(fail){
                fail();
            }
        });
    }

    var config =  {
        cachePath: cachePath,
        basePath: basePath,
        ruby: ruby,
        node_modules: node_modules,
        online: online,
        version: version,
        getUserOptions: getUserOptions,
        saveUserOptions: saveUserOptions,
        checkUpdate: checkUpdate
    };

    //Push to global so other windows can also read configurations
    global.preprosConfig = config;

    return config;

});<commit_msg>Fixed critical bug #130<commit_after>/**
 * Prepros
 * (c) Subash Pathak
 * sbshpthk@gmail.com
 * License: MIT
 */

/*jshint browser: true, node: true*/
/*global prepros, angular, _, $*/

prepros.factory('config', function ($http) {

    'use strict';

    var fs = require('fs-extra'),
        path = require('path'),
        os = require('os');

    //Base path
    var basePath = path.join(path.dirname(process.execPath), 'app');

    //Package.json file url
    var packageFileUrl = path.join(basePath, '../package.json');

    //Read package.json file and get data of app in prepros object
    var packageData = angular.fromJson(fs.readFileSync(packageFileUrl).toString());

    //We need package path because everything is relative to this file
    var packagePath = path.join(basePath, '..');

    //CachePath
    var cachePath = path.join(os.tmpdir(), 'PreprosCache');

    //Node modules required by the app
    var node_modules = packageData.dependencies;

    //App version
    var version = packageData.version;

    //App urls
    var online = {
        url: 'http://alphapixels.com/prepros',
        helpUrl: 'http://alphapixels.com/prepros/docs/',
        loveUrl: 'http://alphapixels.com/prepros#love',
        updateFileUrl: 'https://raw.github.com/sbspk/Prepros/master/package.json',
        githubUrl: 'http://github.com/sbspk/prepros',
        authorTwitter: 'http://twitter.com/sbspk',
        authorUrl: 'http://alphapixels.com'
    };

    //Ruby Executable
    var ruby = {
        path: path.join(packagePath, packageData.ruby.path),
        version: packageData.ruby.version
    };

    //Gems
    ruby.gems = {};
    for ( var gemKey in packageData.ruby.gems ) {

        if(packageData.ruby.gems.hasOwnProperty(gemKey)) {
            ruby.gems[gemKey] = {

                path: path.join(packagePath, packageData.ruby.gems[gemKey].path),
                version: packageData.ruby.gems[gemKey].version
            };
        }
    }

    //Read user config
    var userConfig = {};
    try {

        userConfig = $.parseJSON(localStorage.PreprosConfig || '{}');

    } catch (e) {

        window.alert('Error Reading Configurations ! Reverting to defaults.');

        saveUserOptions(userConfig);
    }

    var defaultConfig = {
        cssPath: 'css',
        jsPath: 'js',
        htmlPath: 'html',
        jsMinPath: 'min',
        htmlExtension: '.html',
        enableSuccessNotifications: true,
        enableErrorNotifications: true,
        filterPatterns: '',
        useCustomRuby: false,
        customRubyPath: '',

        //Default Less Options
        less : {
            autoCompile: true,
            compress : false,
            lineNumbers: false,
            strictMath: true,
            strictUnits: true
        },

        //Default Sass options
        sass : {
            autoCompile : true,
            lineNumbers : false,
            unixNewlines: false,
            debug: false,
            compass : false,
            fullCompass: false,
            outputStyle : 'expanded' //compressed, nested, expanded, compact
        },

        //Default Stylus Options
        stylus : {
            autoCompile: true,
            lineNumbers : false,
            nib : false,
            compress : false
        },

        //Default Markdown Options
        markdown : {
            autoCompile: true,
            sanitize: false,
            gfm: true
        },

        //Default Coffeescript Options
        coffee: {
            autoCompile: true,
            bare: false,
            uglify: false
        },

        //Default javascript options
        javascript: {
            autoCompile: true,
            uglify: true
        },

        //Default Jade  Options
        jade: {
            autoCompile: true,
            pretty: true
        },

        //Default Haml Options
        haml: {
            autoCompile: true,
            format: 'html5', //xhtml, html5
            outputStyle: 'indented', //indented, ugly
            doubleQuotes: false
        },

        //Default Slim  Options
        slim: {
            autoCompile: true,
            pretty: true,
            indent: 'default', //default, four, tab
            fourSpaceIndent: true,
            format: ':html5' //:xhtml, :html4, :html5, :html
        }
    };

    //Fill in the undefined values from default configurations
    userConfig = _.defaults(userConfig, defaultConfig);

    for ( var configKey in userConfig ) {

        if(userConfig.hasOwnProperty(configKey) && typeof userConfig[configKey] === 'object') {

            userConfig[configKey] = _.defaults(userConfig[configKey], defaultConfig[configKey]);
        }
    }

    //Wrap user options in a function to prevent angular data sharing between services
    //If user config data is shared between files changing configuration of one file will affect another file
    function getUserOptions() {

        return $.parseJSON(angular.toJson(userConfig, false));

    }

    function saveUserOptions(options) {

        localStorage.setItem('PreprosConfig', angular.toJson(options));

        userConfig = $.parseJSON(angular.toJson(options));
    }

    function checkUpdate(success, fail){

        var opt = {method: 'get', url: online.updateFileUrl, cache: false};

        var checker = $http(opt);

        checker.success(function(data){

            if(config.version !== data.version) {

                success({
                    available: true,
                    version: data.version,
                    date: data.releaseDate
                });
            } else {
                success({
                    available: false,
                    version: version,
                    date: data.releaseDate
                });
            }
        });

        checker.error(function(data){

            if(fail){
                fail();
            }
        });
    }

    var config =  {
        cachePath: cachePath,
        basePath: basePath,
        ruby: ruby,
        node_modules: node_modules,
        online: online,
        version: version,
        getUserOptions: getUserOptions,
        saveUserOptions: saveUserOptions,
        checkUpdate: checkUpdate
    };

    //Push to global so other windows can also read configurations
    global.preprosConfig = config;

    return config;

});<|endoftext|>