<commit_before>var Filesaver, collections, safename, fs, msgErr, rename;

// get dependencies
safename = require( './safename' );
fs = require( 'fs' );

msgErr = function ( msg ) {
	this.msg = msg;
	this.name = "Error";
}

/**
 * Filesaver constructor.
 *
 * Example:
 *
 * ```js
 * var collections = {
 *     images: './images',
 *     books: './books'
 * }
 * var filesaver = new Filesaver( collections );
 * ```
 *
 * @param {Object} collections Collections schema
 */

Filesaver = function (cols) {
	// Store collections in private
	collections = cols;

	// check for existing folders
	for (col in collections) {
		if (!fs.existsSync( collections[col] )){
			// create folder if not exists
			fs.mkdir( collections[col] );
		}
	}
};

/**
 * Add a new collection
 *
 * Example:
 *
 * ```js
 * filesaver.collection( 'documents', './path/to/folder', function () {
 *     // do something
 * });
 * ```
 * @param  {String}   name       name of new collection
 * @param  {Object}   collection Collection schema
 * @param  {Function} callback   no signature callback
 */

Filesaver.prototype.collection = function (name, folder, callback) {
	// create folder if not exists
	if (!fs.existsSync( folder )) {
		fs.mkdir( folder );
	}
	// add collection
	collections[name] = folder;
	// callback if exists
	if (callback){
		callback();
	}
}

/**
 * Add a new file without overwrite anyone
 *
 * Example:
 *
 * ```js
 * filesaver.add( 'images', '/path/to/temp/file.jpg', 'avatar.jpg', function (err, data) {
 *     console.log( data );
 *     // ->
 *     // filename: 'avatar_2.jpg',
 *     // filepath: './images'
 * });
 * ```
 *
 * @param {String}   collection Name of collection to insert the file
 * @param {String}   origin     path to origin file
 * @param {String}   target     name target file
 * @param {Function} callback   Signature: error, data. Data signature:{filename, filepath}
 */

Filesaver.prototype.add = function (collection, origin, target, callback) {
	// check for valid arguments
	if (collection && origin && (typeof collection === 'string') && (typeof origin === 'string')) {

		var _this = this, checker, filename, destiny, rename;

		/*
		 * +1 to filename sufix if file exists, else callback
		 * @param  {String} path path to check
		 */
		checker = function (path) {
			if (fs.existsSync( '' + collections[collection] + '/' + path )) {

				path = path.split( '_' );
				len = path.length;
				path[len - 1] = 1 + path[len - 1];
				checker( path.join( '_' ), callback);

			} else {
				return _this.replace( collection, origin, path, callback );
			}
		};

		rename = function (path) {

			var splitted, name, split_, num;

			splitdot = path.split( '.' );
			name = splitdot.shift();
			split_ = name.split( '_' );
			num = split_.pop();
			num = 1 + num;
			split_.push( num );
			name = split_.join( '_' );
			splitdot.unshift( name );

			checker( splitdot.join( '.' ));
		}

		// get filename and destiny
		filename = origin.split('/').pop();
		destiny = '' + collections[collection] + '/' + target;

		checker( target, callback );

	} else {
		console.log('error!');
		throw new msgErr( 'Collection or origin not valid' );
	}

}

/**
 * Remove old file and then add the new one
 *
 * Example:
 *
 * ```js
 * filesaver.swap( 'images', '/path/to/temp/file.jpg', 'avatar.jpg', function (err, data) {
 *     console.log( data );
 *     // ->
 *     // filename: 'file.jpg',
 *     // filepath: './images'
 * });
 * ```
 *
 * @param  {String}   collection name of collection
 * @param  {String}   origin     path to origin file
 * @param  {String}   target     name of file to remove
 * @param  {Function} callback   Signature: error, data. Data signature:{filename, filepath}
 */

Filesaver.prototype.swap = function (collection, origin, target, callback) {
	// check for valid arguments
	if (collection && origin && (typeof collection === 'string') && (typeof origin === 'string')) {
		// set target
		var filename = origin.split('/').pop();
		var destiny = '' + collections[collection] + '/' + filename;
		var target = '' + collections[collection] + '/' + target;

		// read origin
		fs.readFile( origin, function (err, data) {
			if (err) {
				callback( err );
			} else {
				// remove target file
				fs.unlinkSync( target );
				// write file
				fs.writeFile( destiny, data, function (err2) {
					if (callback) {
						if (err2) {
							callback( err2 );
						} else {
							callback( null, {
								filename: filename,
								filepath: destiny
							});
						}
					}
				});
			}
		});
	} else {
		throw new msgErr( 'Collection or origin not valid');
	}
}

/**
 * Write or overwrite file
 *
 * Example:
 *
 * ```js
 * filesaver.replace( 'images', '/path/temp/file.jpg', 'avatar.jpg', function (err, data) {
 *     console.log( data );
 *     // ->
 *     // filename: 'avatar.jpg',
 *     // filepath: './images'
 *     });
 * ```
 *
 * @param  {String}   collection name of parent collection
 * @param  {String}   origin     path to origin file
 * @param  {String}   target     name of target file
 * @param  {Function} callback   Signature: error, data. Data signature:{filename, filepath}
 */

Filesaver.prototype.replace = function (collection, origin, target, callback) {

	// check for valid arguments
	if (collection && origin && (typeof collection === 'string') && (typeof origin === 'string')) {

		// set target
		var destiny = '' + collections[collection] + '/' + target;

		// read origin
		fs.readFile( origin, function (err, data) {
			if (err) {
				callback( err );
			} else {
				// write file
				fs.writeFile( destiny, data, function (err2) {
					if (err2) {
						callback( err2 );
					} else {
						callback( null, {
							filename: destiny.split('/').pop(),
							filepath: destiny
						});
					}
				});
			}
		});
	} else {
		throw new msgErr( 'Collection or origin not valid');
	}
}

module.exports = Filesaver;
<commit_msg>New fixed add method<commit_after>var Filesaver, collections, safename, fs, msgErr, rename;

// get dependencies
safename = require( './safename' );
fs = require( 'fs' );

/* private methods */

msgErr = function ( msg ) {
	this.msg = msg;
	this.name = "Error";
}

var firstsufix = function (name) {
	var splitted, suff;
	splitted = name.split( '_' );
	if (splitted.length === 1) {
		return '' + name + '_0';
	} else {
		suff = splitted.pop();
		if (Number(suff) === NaN) {
			return '' + name + '_0';
		} else {
			return name;
		}
	}
}

var add1 = function (name) {
	var splitted, sufix;
	splitted = name.split( '_' );
	sufix = splitted.pop();
	sufix = 1 + Number( sufix );
	splitted.push( sufix );
	return splitted.join( '_' );
}

var joinplused = function (arr) {
	arr[0] = add1( arr[0] );
	return arr.join( '.' );
}

var splitName = function (name) {
	var arr, name, ext;
	arr = name.split('.');
	name = arr.shift();
	ext = arr.join('.');
	return [name, ext];
}

var renamer = function (name) {
	return joinplused( splitName( name ));
}

/**
 * Filesaver constructor.
 *
 * Example:
 *
 * ```js
 * var collections = {
 *     images: './images',
 *     books: './books'
 * }
 * var filesaver = new Filesaver( collections );
 * ```
 *
 * @param {Object} collections Collections schema
 */

Filesaver = function (cols) {
	// Store collections in private
	collections = cols;

	// check for existing folders
	for (col in collections) {
		if (!fs.existsSync( collections[col] )){
			// create folder if not exists
			fs.mkdir( collections[col] );
		}
	}
};

/**
 * Add a new collection
 *
 * Example:
 *
 * ```js
 * filesaver.collection( 'documents', './path/to/folder', function () {
 *     // do something
 * });
 * ```
 * @param  {String}   name       name of new collection
 * @param  {Object}   collection Collection schema
 * @param  {Function} callback   no signature callback
 */

Filesaver.prototype.collection = function (name, folder, callback) {
	// create folder if not exists
	if (!fs.existsSync( folder )) {
		fs.mkdir( folder );
	}
	// add collection
	collections[name] = folder;
	// callback if exists
	if (callback){
		callback();
	}
}

/**
 * Add a new file without overwrite anyone
 *
 * Example:
 *
 * ```js
 * filesaver.add( 'images', '/path/to/temp/file.jpg', 'avatar.jpg', function (err, data) {
 *     console.log( data );
 *     // ->
 *     // filename: 'avatar_2.jpg',
 *     // filepath: './images'
 * });
 * ```
 *
 * @param {String}   collection Name of collection to insert the file
 * @param {String}   origin     path to origin file
 * @param {String}   target     name target file
 * @param {Function} callback   Signature: error, data. Data signature:{filename, filepath}
 */

Filesaver.prototype.add = function (collection, origin, target, callback) {
	// check for valid arguments
	if (collection && origin && (typeof collection === 'string') && (typeof origin === 'string')) {

		var _this = this, checker, filename, destiny, rename, toCheck;

		/*
		 * +1 to filename sufix if file exists, else callback
		 * @param  {String} path path to check
		 */
		checker = function (path) {
			if (fs.existsSync( '' + collections[collection] + '/' + path )) {

				checker( renamer(path), callback);

			} else {
				return _this.replace( collection, origin, path, callback );
			}
		};

		rename = function (path) {
			var splitted, name, split_, num;

			splitdot = path.split( '.' );
			name = splitdot.shift();
			split_ = name.split( '_' );
			num = split_.pop();
			num = 1 + num;
			split_.push( num );
			name = split_.join( '_' );
			splitdot.unshift( name );

			checker( splitdot.join( '.' ));
		}

		// get filename and destiny
		filename = origin.split('/').pop();
		destiny = '' + collections[collection] + '/' + target;

		if (fs.existsSync( destiny )) {

			toCheck = [ firstsufix( splitName(target)[0] ), splitName(target)[1] ].join( '.' );

			checker( toCheck, callback);

		} else {
			return _this.replace( collection, origin, target, callback );
		}

	} else {
		console.log('error!');
		throw new msgErr( 'Collection or origin not valid' );
	}

}

/**
 * Remove old file and then add the new one
 *
 * Example:
 *
 * ```js
 * filesaver.swap( 'images', '/path/to/temp/file.jpg', 'avatar.jpg', function (err, data) {
 *     console.log( data );
 *     // ->
 *     // filename: 'file.jpg',
 *     // filepath: './images'
 * });
 * ```
 *
 * @param  {String}   collection name of collection
 * @param  {String}   origin     path to origin file
 * @param  {String}   target     name of file to remove
 * @param  {Function} callback   Signature: error, data. Data signature:{filename, filepath}
 */

Filesaver.prototype.swap = function (collection, origin, target, callback) {
	// check for valid arguments
	if (collection && origin && (typeof collection === 'string') && (typeof origin === 'string')) {
		// set target
		var filename = origin.split('/').pop();
		var destiny = '' + collections[collection] + '/' + filename;
		var target = '' + collections[collection] + '/' + target;

		// read origin
		fs.readFile( origin, function (err, data) {
			if (err) {
				callback( err );
			} else {
				// remove target file
				fs.unlinkSync( target );
				// write file
				fs.writeFile( destiny, data, function (err2) {
					if (callback) {
						if (err2) {
							callback( err2 );
						} else {
							callback( null, {
								filename: filename,
								filepath: destiny
							});
						}
					}
				});
			}
		});
	} else {
		throw new msgErr( 'Collection or origin not valid');
	}
}

/**
 * Write or overwrite file
 *
 * Example:
 *
 * ```js
 * filesaver.replace( 'images', '/path/temp/file.jpg', 'avatar.jpg', function (err, data) {
 *     console.log( data );
 *     // ->
 *     // filename: 'avatar.jpg',
 *     // filepath: './images'
 *     });
 * ```
 *
 * @param  {String}   collection name of parent collection
 * @param  {String}   origin     path to origin file
 * @param  {String}   target     name of target file
 * @param  {Function} callback   Signature: error, data. Data signature:{filename, filepath}
 */

Filesaver.prototype.replace = function (collection, origin, target, callback) {

	// check for valid arguments
	if (collection && origin && (typeof collection === 'string') && (typeof origin === 'string')) {

		// set target
		var destiny = '' + collections[collection] + '/' + target;

		// read origin
		fs.readFile( origin, function (err, data) {
			if (err) {
				callback( err );
			} else {
				// write file
				fs.writeFile( destiny, data, function (err2) {
					if (err2) {
						callback( err2 );
					} else {
						callback( null, {
							filename: destiny.split('/').pop(),
							filepath: destiny
						});
					}
				});
			}
		});
	} else {
		throw new msgErr( 'Collection or origin not valid');
	}
}

module.exports = Filesaver;
<|endoftext|>


<commit_before>/* global define, evaluatePhase */
/*jslint bitwise: true */
(function (window) {
  'use strict';

  var FirFilter = function (filter) {
    // note: coefficients are equal to input response
    var f = filter;
    var initZero = function (cnt) {
      var r = [];
      var i;
      for (i = 0; i < cnt; i++) {
        r.push(0);
      }
      return {
        buf: r,
        pointer: 0
      };
    };
    var z = initZero(f.length - 1);
    var cnt = 0;
    var doStep = function (input, d) {
      d.buf[d.pointer] = input;
      var out = 0;
      for (cnt = 0; cnt < d.buf.length; cnt++) {
        out += (f[cnt] * d.buf[(d.pointer + cnt) % d.buf.length]);
      }
      d.pointer += 1 % d.buf.length;
      return out;
    };

    var re = [];
    var im = [];
    var dft = function (coeffs) {
      re.length = 0;
      im.length = 0;
      var ret = [];
      var n = coeffs.length;
      var half = n / 2;
      var cnt = 0;
      var k = 0;
      var c = 2 * Math.PI / n;
      for (k = 0; k <= half; k++) {
        re[k] = 0;
        im[k] = 0;
      }
      for (k = 0; k <= half; k++) {
        for (cnt = 0; cnt < n; cnt++) {
          re[k] += coeffs[cnt] * Math.cos(c * k * cnt);
          im[k] -= coeffs[cnt] * Math.sin(c * k * cnt);
        }
        ret[k] = {};
        ret[k].magnitude = Math.sqrt(re[k] * re[k] + im[k] * im[k]);
        ret[k].dBmagnitude = 20 * Math.log(ret[k].magnitude) * Math.LOG10E;
        if (re[k] === 0) {
          re[k] = -Number.MAX_VALUE;
        }
        ret[k].phase = Math.atan2(im[k], re[k]);
      }
      return ret;
    };
    var self = {
      response: function () {
        var input = [];
        var cnt = 0;
        for (cnt = 0; cnt < f.length * 2; cnt++) {
          if (f[cnt]) {
            input.push(f[cnt]);
          } else {
            input.push(0);
          }
        }
        var res = dft(input);
        evaluatePhase(res);
        return res;
      },
      singleStep: function (input) {
        return doStep(input, z);
      },
      multiStep: function (input) {
        var out = [];
        for (cnt = 0; cnt < input.length; cnt++) {
          out.push(doStep(input[cnt], z));
        }
        return out;
      },
      reinit: function () {
        z = initZero(f.length - 1);
      }
    };
    return self;
  };

  if (typeof module === 'object' && module && typeof module.exports === 'object') {
    module.exports = FirFilter;
  } else {
    window.FirFilter = FirFilter;
    if (typeof define === 'function' && define.amd) {
      define(FirFilter);
    }
  }
})(window);
<commit_msg>error in multiple execution<commit_after>/* global define, evaluatePhase */
/*jslint bitwise: true */
(function (window) {
  'use strict';

  var FirFilter = function (filter) {
    // note: coefficients are equal to input response
    var f = filter;
    var initZero = function (cnt) {
      var r = [];
      var i;
      for (i = 0; i < cnt; i++) {
        r.push(0);
      }
      return {
        buf: r,
        pointer: 0
      };
    };
    var z = initZero(f.length - 1);
    var cnt = 0;
    var doStep = function (input, d) {
      d.buf[d.pointer] = input;
      var out = 0;
      for (cnt = 0; cnt < d.buf.length; cnt++) {
        out += (f[cnt] * d.buf[(d.pointer + cnt) % d.buf.length]);
      }
      d.pointer = (d.pointer + 1) % (d.buf.length);
      return out;
    };

    var re = [];
    var im = [];
    var dft = function (coeffs) {
      re.length = 0;
      im.length = 0;
      var ret = [];
      var n = coeffs.length;
      var half = n / 2;
      var cnt = 0;
      var k = 0;
      var c = 2 * Math.PI / n;
      for (k = 0; k <= half; k++) {
        re[k] = 0;
        im[k] = 0;
      }
      for (k = 0; k <= half; k++) {
        for (cnt = 0; cnt < n; cnt++) {
          re[k] += coeffs[cnt] * Math.cos(c * k * cnt);
          im[k] -= coeffs[cnt] * Math.sin(c * k * cnt);
        }
        ret[k] = {};
        ret[k].magnitude = Math.sqrt(re[k] * re[k] + im[k] * im[k]);
        ret[k].dBmagnitude = 20 * Math.log(ret[k].magnitude) * Math.LOG10E;
        if (re[k] === 0) {
          re[k] = -Number.MAX_VALUE;
        }
        ret[k].phase = Math.atan2(im[k], re[k]);
      }
      return ret;
    };
    var self = {
      response: function () {
        var input = [];
        var cnt = 0;
        for (cnt = 0; cnt < f.length * 2; cnt++) {
          if (f[cnt]) {
            input.push(f[cnt]);
          } else {
            input.push(0);
          }
        }
        var res = dft(input);
        evaluatePhase(res);
        return res;
      },
      singleStep: function (input) {
        return doStep(input, z);
      },
      multiStep: function (input) {
        var out = [];
        var i;
        for (i = 0; i < input.length; i++) {
          out.push(doStep(input[i], z));
        }
        return out;
      },
      reinit: function () {
        z = initZero(f.length - 1);
      }
    };
    return self;
  };

  if (typeof module === 'object' && module && typeof module.exports === 'object') {
    module.exports = FirFilter;
  } else {
    window.FirFilter = FirFilter;
    if (typeof define === 'function' && define.amd) {
      define(FirFilter);
    }
  }
})(window);
<|endoftext|>


<commit_before>import { postgresConnection as cn } from '../../config/helpers.js';
import { QueryFile } from 'pg-promise';
const pgp = require('pg-promise')();
const db = pgp(cn);

function sql(file) {
  return new QueryFile(__dirname + "/" + file, { minify: true });
}

// get user follows count for any user
// UNUSED
// const getUserFollowCount = (request, response) => {
//   console.log(request.query);
//   // in query: .user
//   db.query(sql('getUserFollowCount.sql'), request.query)
//     .then(data => { response.json(data); })
//     .catch(data => { response.json(data); });
// };

// get recipe follows count for any recipe
// UNUSED
// const getRecipeFollowCount = (request, response) => {
//   console.log(request.query);
//   // in params: .recipe_id
//   db.query(sql('getRecipeFollowCount.sql'), request.params)
//     .then(data => { response.json(data); })
//     .catch(data => { response.json(data); });
// };

// get user follows count and user follow status for logged in user
// HTTP GET
export const getUserFollowState = (request, response) => {
  console.log(request.query);
  // in query: .follower, .target
  db.query(sql('getUserFollowState.sql'), request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// get recipe follows count and recipe follow status for logged in user
// HTTP GET
export const getRecipeFollowState = (request, response, next) => {
  console.log(request.query);
  // in query: .user_id, .recipe_id
  db.query(sql('getRecipeFollowState.sql'), request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// add new user follow for logged in user
// HTTP POST
const addUserFollow = (request, response) => {
  // does not verify that both users exist before
  // inserting a new follow
  console.log(request.body);
  // body: .follower, .target
  db.query(sql('addUserFollow.sql'), request.body)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// add new recipe follow for logged in user
// HTTP POST
const addRecipeFollow = (request, response) => {
  // does not verify that a user or a recipe exists before
  // inserting a new follow
  console.log(request.body);
  // body: .user_id, .recipe_id
  db.query(sql('addRecipeFollow.sql'), request.body)
    .then(data => { console.log('data', data); response.json(data); })
    .catch(error => { response.json(error); });
};

// remove user follow for logged in user
const removeUserFollow = (request, response) => {
  console.log(request.query);
  // in query: .follower, .target
  db.query(sql('removeUserFollow.sql'), request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// remove recipe follow for logged in user
const removeRecipeFollow = (request, response) => {
  console.log(request.query);
  // in query: .user_id, .recipe_id
  db.query(sql('removeRecipeFollow.sql'), request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// decide whether to add or remove user follow, based on user intent
export const addOrRemoveUserFollow = (request, response) => {
  if (request.query.followState) {
    removeUserFollow(request, response);
  } else {
    addUserFollow(request, response);
  }
};

// decide whether to add or remove recipe follow, based on user intent
export const addOrRemoveRecipeFollow = (request, response) => {
  if (request.query.followState) {
    removeRecipeFollow(request, response);
  } else {
    addRecipeFollow(request, response);
  }
};

// get a list of every user the current user follows
// HTTP GET
export const getAllFollowedUsers = (request, response) {
  // TODO: pagination
  console.log(request.query);
  // in query: .user_id
  db.query('getAllFollowedUsers.sql', request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.data(error); });
};

export const getAllFollowedRecipes = (request, response) {
  console.log(request.query);
  // in query: .user_id
  db.query('getAllFollowedRecipes.sql', request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.data(error); });
};
<commit_msg>Add todo markers, console log cleanup<commit_after>import { postgresConnection as cn } from '../../config/helpers.js';
import { QueryFile } from 'pg-promise';
const pgp = require('pg-promise')();
const db = pgp(cn);

function sql(file) {
  return new QueryFile(__dirname + "/" + file, { minify: true });
}

// get user follows count for any user
// UNUSED
// const getUserFollowCount = (request, response) => {
//   console.log(request.query);
//   // in query: .user
//   db.query(sql('getUserFollowCount.sql'), request.query)
//     .then(data => { response.json(data); })
//     .catch(data => { response.json(data); });
// };

// get recipe follows count for any recipe
// UNUSED
// const getRecipeFollowCount = (request, response) => {
//   console.log(request.query);
//   // in params: .recipe_id
//   db.query(sql('getRecipeFollowCount.sql'), request.params)
//     .then(data => { response.json(data); })
//     .catch(data => { response.json(data); });
// };

// get user follows count and user follow status for logged in user
// HTTP GET
export const getUserFollowState = (request, response) => {
  console.log(request.query);
  // in query: .follower, .target
  db.query(sql('getUserFollowState.sql'), request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// get recipe follows count and recipe follow status for logged in user
// HTTP GET
export const getRecipeFollowState = (request, response, next) => {
  console.log(request.query);
  // in query: .user_id, .recipe_id
  db.query(sql('getRecipeFollowState.sql'), request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// add new user follow for logged in user
// HTTP POST
const addUserFollow = (request, response) => {
  // TODO: does not verify that both users exist before
  //       inserting a new user follow
  console.log(request.body);
  // body: .follower, .target
  db.query(sql('addUserFollow.sql'), request.body)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// add new recipe follow for logged in user
// HTTP POST
const addRecipeFollow = (request, response) => {
  // TODO: does not verify that a user or a recipe exists before
  //       inserting a new recipe follow
  console.log(request.body);
  // body: .user_id, .recipe_id
  db.query(sql('addRecipeFollow.sql'), request.body)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// remove user follow for logged in user
const removeUserFollow = (request, response) => {
  console.log(request.query);
  // in query: .follower, .target
  db.query(sql('removeUserFollow.sql'), request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// remove recipe follow for logged in user
const removeRecipeFollow = (request, response) => {
  console.log(request.query);
  // in query: .user_id, .recipe_id
  db.query(sql('removeRecipeFollow.sql'), request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.json(error); });
};

// decide whether to add or remove user follow, based on user intent
export const addOrRemoveUserFollow = (request, response) => {
  if (request.query.followState) {
    removeUserFollow(request, response);
  } else {
    addUserFollow(request, response);
  }
};

// decide whether to add or remove recipe follow, based on user intent
export const addOrRemoveRecipeFollow = (request, response) => {
  if (request.query.followState) {
    removeRecipeFollow(request, response);
  } else {
    addRecipeFollow(request, response);
  }
};

// get a list of every user the current user follows
// HTTP GET
export const getAllFollowedUsers = (request, response) {
  // TODO: pagination
  console.log(request.query);
  // in query: .user_id
  db.query('getAllFollowedUsers.sql', request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.data(error); });
};

export const getAllFollowedRecipes = (request, response) {
  console.log(request.query);
  // in query: .user_id
  db.query('getAllFollowedRecipes.sql', request.query)
    .then(data => { response.json(data); })
    .catch(error => { response.data(error); });
};
<|endoftext|>


<commit_before>/**
 * Capture device packets, send them to server and store them.
 * Queue and re-send them later if not connected.
 */
"use strict";

var NoGapDef = require('nogap').Def;

module.exports = NoGapDef.component({
    Includes: [
        // add all device-only components here
    ],

    /**
     * Everything defined in `Base` is available on Host and Client.
     */
    Base: NoGapDef.defBase(function(SharedTools, Shared, SharedContext) { return {
        /**
         *
         */
        initBase: function() {

        },
    };}),

    /**
     * Everything defined in `Host` lives only on the host side (Node).
     */
    Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) {
        return {
            __ctor: function() {
            },
            initHost: function() {
            },

        Private: {
            onClientBootstrap: function() {
            }
        },

        /**
         * Host commands can be directly called by the client
         */
        Public: {
            storePacket: function(packet) {
            	var user = this.Instance.User.currentUser;
                if (!this.Instance.User.isDevice()) return Promise.reject('error.invalid.permissions');

                var device = this.Instance.DeviceMain.getCurrentDevice();
                if (!device) {
                	// internal error: something went wrong in our authentication process
                	throw new Error('Device was logged in with its user account, but device entry was not ready: ' +
                		user.userName);
                }
                packet.deviceId = device.deviceId;
                // call stored procedure to take care of packet insertion
                return sequelize.query('CALL storePacket(?, ?, ?, ?, ?, ?);', {
                    replacements: [
                        packet.mac,
                        packet.signalStrength,
                        packet.time,
                        packet.seqnum,
                        packet.ssid || '',
                        packet.deviceId
                    ],
                    type: sequelize.QueryTypes.RAW
                });
                // .spread(function() {

                // });
            },
            storePacket2: function(packet) {
            	var user = this.Instance.User.currentUser;
                if (!this.Instance.User.isDevice()) return Promise.reject('error.invalid.permissions');

                var device = this.Instance.DeviceMain.getCurrentDevice();
                if (!device) {
                	// internal error: something went wrong in our authentication process
                	throw new Error('Device was logged in with its user account, but device entry was not ready: ' +
                		user.userName);
                }
                packet.deviceId = device.deviceId;
                // call stored procedure to take care of packet insertion
                return sequelize.query('CALL storePacket2(?, ?, ?, ?, ?);', {
                    replacements: [
                        packet.mac,
                        packet.signalStrength,
                        packet.time,
                        packet.seqnum,
                        packet.deviceId
                    ],
                    type: sequelize.QueryTypes.RAW
                });
                // .spread(function() {

                // });
            }
        },
    }}),

    /**
     * Everything defined in `Client` lives only in the client (browser).
     */
    Client: NoGapDef.defClient(function(Tools, Instance, Context) {
        var ThisComponent;
        var pcap;
        var sys;
        var exec;
        var Queue;
        var queue;
        var promisify;

        return {
            __ctor: function() {
                ThisComponent = this;
                try {
                    pcap = require('pcap');
                }
                catch (err) {
                    console.error('[ERROR] pcap is not available');
                }
                sys = require('sys');
                exec = require('child_process').exec;
                Queue = require('file-queue').Queue;
                promisify = require("promisify-node");
            },

            /**
             * Send packet to server or put in queue, if we failed.
             */
            storePacket: function(packet) {
                // send packet to server
                return this.host.storePacket(packet)
                .then(function() {
                    Instance.DeviceLog.logStatus("packet sent successfully!");
                    // DB successfully stored packet
                })
                .catch(function(err) {
                    Instance.DeviceLog.logError('storePacket on Host failed - ' + err.stack, true);

                    // could not send packet to server -> Store in queue...
                    return new Promise(function(resolve, reject) {
                        queue.push(packet, function(err) {
                            if(err) reject(err);
                            else {
                                // TODO: Why query length here?
                                queue.length(function(err,len) { console.log(len); });
                                resolve();
                            }
                        });
                    });
                });
            },

            storePacket2: function(packet) {
                // send packet to server
                return this.host.storePacket2(packet)
                .then(function() {
                    Instance.DeviceLog.logStatus("packet2 sent successfully!");
                    // DB successfully stored packet
                })
                .catch(function(err) {
                    Instance.DeviceLog.logError('storePacket2 on Host failed - ' + err.stack, true);

                    // could not send packet to server -> Store in queue...
                    return new Promise(function(resolve, reject) {
                        queue.push(packet, function(err) {
                            if(err) reject(err);
                            else {
                                // TODO: Why query length here?
                                queue.length(function(err,len) { console.log(len); });
                                resolve();
                            }
                        });
                    });
                });
            },
            structToMac: function(struct) {
                var result = "";
                var l;
                for(var i = 0; i<6; i++)
                        {
                        l = struct[i].toString(16);
                        result += l.length === 1 ? '0' + l: l;
		        }
        	   return result;
            },

            preCapture: function() {
                return Promise.join(
	                Instance.DeviceMain.execAsync("/usr/sbin/ntpdate -s ntp.nict.jp clock.tl.fukuoka-u.ac.jp clock.nc.fukuoka-u.ac.jp")
                        .catch(function(err) {
                            Instance.DeviceLog.logError('ntpdate failed - ' + err.stack || err, true);
                        }),
            	    Instance.DeviceMain.execAsync("ntp-wait -v")
                        .catch(function(err) {
                            Instance.DeviceLog.logError('ntp-wait failed - ' + err.stack || err, true);
                        }),
                    Instance.DeviceMain.execAsync("iw phy phy0 interface add mon0 type monitor")
                        .catch(function(err) {
                            Instance.DeviceLog.logError('iw failed - ' + err.stack || err, true);
                        }),
                    Instance.DeviceMain.execAsync("ifconfig mon0 up")
                        .catch(function(err) {
                            Instance.DeviceLog.logError('ifconfig failed - ' + err.stack || err, true);
                        }),
                    new Promise(function(resolve, reject) {
                        queue = new Queue('tmp/', function(err, stdout, stderr) {
                            if(err) return reject(err);
                            ThisComponent.flushQueue();
                            resolve();
                        });
                    })
                );
            },

            processPacket: function(packet) {
                var result = {};
                result.mac = ThisComponent.structToMac(packet.payload.ieee802_11Frame.shost.addr);
                result.signalStrength = packet.payload.signalStrength;
                result.time = packet.pcap_header.tv_sec+(packet.pcap_header.tv_usec/1000000);
                result.seqnum = packet.payload.ieee802_11Frame.fragSeq >> 4;
                result.ssid = packet.payload.ieee802_11Frame.probe.tags[0].ssid;
                return ThisComponent.storePacket(result);
            },

            basicProcessor: function(packet) {
                var result = {};
                result.signalStrength = packet.payload.signalStrength;
                result.mac = ThisComponent.structToMac(packet.payload.ieee802_11Frame.shost.addr);
                result.seqnum = packet.payload.ieee802_11Frame.fragSeq >> 4;
                result.time = packet.pcap_header.tv_sec+(packet.pcap_header.tv_usec/1000000);
                if(result.signalStrength >= -25) {
                    return ThisComponent.storePacket2(result);
                }
            },

            flushQueue: function() {
                Instance.DeviceLog.logStatus('flushQueue', true);
                var dummies = [];
                queue.length(function(err, length) {
                    if (!length) return;

                    for(var i=0; i<length; i++) {
                        dummies.push(0);
                    }

                    return Promise.map(dummies, function(dummy) {
                        return new Promise(function(resolve, reject) {
                            queue.tpop(function(err, packet, commit, rollback) {
                                if (err)
                                    {
                                    reject(err);
                                    }
                                ThisComponent.host.storePacket(packet)
                                .then(function() {
                                    commit(function(err) {
                                        if (err) {
                                            reject(err);
                                        }
                                        else {
                                            resolve();
                                        }
                                    });
                                })
                                .catch(function(err) {
                                    rollback(function(err2) {
                                        if (err2) {
                                            Instance.DeviceLog.logError('Unable to rollback: ' + err2.stack, true);
                                        }
                                        //reject(err);
                                        resolve();
                                    });
                                });
                            });
                        });
                    }, {
                        concurrency: 5              // how many packets in-flight, at the same time
                    })
                    .then(function() {
                        Instance.DeviceLog.logStatus('DeviceCapture file queue flushed!', true);
                    });
                });

                /*queue.length(function(err, length) {
                    for(var i=0; i<5; i++) {
                        queue.tpop(function(err, packet, commit, rollback) {
                            ThisComponent.host.storePacket(packet)
                                .then(function() { commit(function(err) { if(err) throw err; console.log("Stored Packet uploaded");})})
                                .catch(function() { rollback(function(err) { if (err) throw err; console.log("Stored Packet Problem");})});
                        });
                    }
                });*/
            },

            startCapturing: function(device) {
                if (!pcap) return;
                if (this.isCapturing) return;   // don't do anything

                this.isCapturing = true;
                Instance.DeviceLog.logStatus('Preparing DeviceCapture...', true);

                ThisComponent.preCapture()
                .then(function() {
                    Instance.DeviceLog.logStatus('Starting DeviceCapture...', true);

                    var device = Instance.DeviceMain.getCurrentDevice();
                    var jobType = Instance.WifiSnifferDevice.DeviceJobType;
                    var pcap_session;
                    if(device.currentJobType == jobType.ActivitySniffer) {
                        pcap_session = pcap.createSession("mon0", "wlan type mgt || wlan type data");
                        pcap_session.on('packet', function(raw_packet) {
                            return Promise.resolve()
                            .then(function() {
                                var packet = pcap.decode.packet(raw_packet);
                                return ThisComponent.basicProcessor(packet);
                            });
                        });
                    }
                    else {
                        pcap_session = pcap.createSession("mon0", "wlan type mgt subtype probe-req");
                        pcap_session.on('packet', function(raw_packet) {
                            return Promise.resolve()
                            .then(function() {
                                var packet = pcap.decode.packet(raw_packet);
                                return ThisComponent.processPacket(packet);
                            })
                            .catch(function(err) {
                                Instance.DeviceLog.logError('DeviceCapture.processPacket failed  - ' + err.stack, true);
                            });
                        });
                    }
                });
            },

            /**
             * Client commands can be directly called by the host
             */
            Public: {

            }
        };
    })
});
<commit_msg>- fixed DeviceCapture bug + some formatting, as discussed in in-class code review<commit_after>/**
 * Capture device packets, send them to server and store them.
 * Queue and re-send them later if not connected.
 */
"use strict";

var NoGapDef = require('nogap').Def;

module.exports = NoGapDef.component({
    Includes: [
        // add all device-only components here
    ],

    /**
     * Everything defined in `Base` is available on Host and Client.
     */
    Base: NoGapDef.defBase(function(SharedTools, Shared, SharedContext) { return {
        /**
         *
         */
        initBase: function() {

        },
    };}),

    /**
     * Everything defined in `Host` lives only on the host side (Node).
     */
    Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) {
        return {
            __ctor: function() {
            },
            initHost: function() {
            },

        Private: {
            onClientBootstrap: function() {
            }
        },

        /**
         * Host commands can be directly called by the client
         */
        Public: {
            storePacket: function(packet) {
            	var user = this.Instance.User.currentUser;
                if (!this.Instance.User.isDevice()) return Promise.reject('error.invalid.permissions');

                var device = this.Instance.DeviceMain.getCurrentDevice();
                if (!device) {
                	// internal error: something went wrong in our authentication process
                	throw new Error('Device was logged in with its user account, but device entry was not ready: ' +
                		user.userName);
                }
                packet.deviceId = device.deviceId;
                // call stored procedure to take care of packet insertion
                return sequelize.query('CALL storePacket(?, ?, ?, ?, ?, ?);', {
                    replacements: [
                        packet.mac,
                        packet.signalStrength,
                        packet.time,
                        packet.seqnum,
                        packet.ssid || '',
                        packet.deviceId
                    ],
                    type: sequelize.QueryTypes.RAW
                });
                // .spread(function() {

                // });
            },
            storePacket2: function(packet) {
            	var user = this.Instance.User.currentUser;
                if (!this.Instance.User.isDevice()) return Promise.reject('error.invalid.permissions');

                var device = this.Instance.DeviceMain.getCurrentDevice();
                if (!device) {
                	// internal error: something went wrong in our authentication process
                	throw new Error('Device was logged in with its user account, but device entry was not ready: ' +
                		user.userName);
                }
                packet.deviceId = device.deviceId;
                // call stored procedure to take care of packet insertion
                return sequelize.query('CALL storePacket2(?, ?, ?, ?, ?);', {
                    replacements: [
                        packet.mac,
                        packet.signalStrength,
                        packet.time,
                        packet.seqnum,
                        packet.deviceId
                    ],
                    type: sequelize.QueryTypes.RAW
                });
                // .spread(function() {

                // });
            }
        },
    }}),

    /**
     * Everything defined in `Client` lives only in the client (browser).
     */
    Client: NoGapDef.defClient(function(Tools, Instance, Context) {
        var ThisComponent;
        var pcap;
        var sys;
        var exec;
        var Queue;
        var queue;
        var promisify;

        return {
            __ctor: function() {
                ThisComponent = this;
                try {
                    pcap = require('pcap');
                }
                catch (err) {
                    console.error('[ERROR] pcap is not available');
                }
                sys = require('sys');
                exec = require('child_process').exec;
                Queue = require('file-queue').Queue;
                promisify = require("promisify-node");
            },

            /**
             * Send packet to server or put in queue, if we failed.
             */
            storePacket: function(packet) {
                // send packet to server
                return this.host.storePacket(packet)
                .then(function() {
                    Instance.DeviceLog.logStatus("packet sent successfully!");
                    // DB successfully stored packet
                })
                .catch(function(err) {
                    Instance.DeviceLog.logError('storePacket on Host failed - ' + err.stack, true);

                    // could not send packet to server -> Store in queue...
                    return new Promise(function(resolve, reject) {
                        queue.push(packet, function(err) {
                            if(err) return reject(err);

                            // TODO: Why query length here?
                            queue.length(function(err,len) { console.log(len); });
                            resolve();
                        });
                    });
                });
            },

            storePacket2: function(packet) {
                // send packet to server
                return this.host.storePacket2(packet)
                .then(function() {
                    Instance.DeviceLog.logStatus("packet2 sent successfully!");
                    // DB successfully stored packet
                })
                .catch(function(err) {
                    Instance.DeviceLog.logError('storePacket2 on Host failed - ' + err.stack, true);

                    // could not send packet to server -> Store in queue...
                    return new Promise(function(resolve, reject) {
                        queue.push(packet, function(err) {
                            if(err) return reject(err);

                            // TODO: Why query length here?
                            queue.length(function(err,len) { console.log(len); });
                            resolve();
                        });
                    });
                });
            },

            structToMac: function(struct) {
                var result = "";
                var len;
                for(var i = 0; i<6; i++) {
                    len = struct[i].toString(16);
                    result += len.length === 1 ? ('0' + len) : len;
		        }
        	   return result;
            },

            preCapture: function() {
                return Promise.join(
	                Instance.DeviceMain.execAsync("/usr/sbin/ntpdate -s ntp.nict.jp clock.tl.fukuoka-u.ac.jp clock.nc.fukuoka-u.ac.jp")
                        .catch(function(err) {
                            Instance.DeviceLog.logError('ntpdate failed - ' + err.stack || err, true);
                        }),
            	    Instance.DeviceMain.execAsync("ntp-wait -v")
                        .catch(function(err) {
                            Instance.DeviceLog.logError('ntp-wait failed - ' + err.stack || err, true);
                        }),
                    Instance.DeviceMain.execAsync("iw phy phy0 interface add mon0 type monitor")
                        .catch(function(err) {
                            Instance.DeviceLog.logError('iw failed - ' + err.stack || err, true);
                        }),
                    Instance.DeviceMain.execAsync("ifconfig mon0 up")
                        .catch(function(err) {
                            Instance.DeviceLog.logError('ifconfig failed - ' + err.stack || err, true);
                        }),
                    new Promise(function(resolve, reject) {
                        queue = new Queue('tmp/', function(err, stdout, stderr) {
                            if(err) return reject(err);

                            ThisComponent.flushQueue();
                            resolve();
                        });
                    })
                );
            },

            processPacket: function(packet) {
                var result = {};
                result.mac = ThisComponent.structToMac(packet.payload.ieee802_11Frame.shost.addr);
                result.signalStrength = packet.payload.signalStrength;
                result.time = packet.pcap_header.tv_sec+(packet.pcap_header.tv_usec/1000000);
                result.seqnum = packet.payload.ieee802_11Frame.fragSeq >> 4;
                result.ssid = packet.payload.ieee802_11Frame.probe.tags[0].ssid;
                return ThisComponent.storePacket(result);
            },

            basicProcessor: function(packet) {
                var result = {};
                result.signalStrength = packet.payload.signalStrength;
                result.mac = ThisComponent.structToMac(packet.payload.ieee802_11Frame.shost.addr);
                result.seqnum = packet.payload.ieee802_11Frame.fragSeq >> 4;
                result.time = packet.pcap_header.tv_sec+(packet.pcap_header.tv_usec/1000000);
                if(result.signalStrength >= -25) {
                    return ThisComponent.storePacket2(result);
                }
            },

            flushQueue: function() {
                Instance.DeviceLog.logStatus('flushQueue', true);
                var dummies = [];
                queue.length(function(err, length) {
                    if (!length) return;

                    for(var i=0; i<length; i++) {
                        dummies.push(0);
                    }

                    return Promise.map(dummies, function(dummy) {
                        return new Promise(function(resolve, reject) {
                            queue.tpop(function(err, packet, commit, rollback) {
                                if (err) return reject(err);

                                ThisComponent.host.storePacket(packet)
                                .then(function() {
                                    commit(function(err) {
                                        if (err) return reject(err);

                                        resolve();
                                    });
                                })
                                .catch(function(err) {
                                    // something went wrong -> Rollback
                                    rollback(function(err2) {
                                        if (err2) {
                                            Instance.DeviceLog.logError('Unable to rollback: ' + err2.stack, true);
                                            //return reject(err);
                                        }

                                        // just resolve anyway
                                        resolve();
                                    });
                                });
                            });
                        });
                    }, {
                        concurrency: 5              // how many packets in-flight, at the same time
                    })
                    .then(function() {
                        Instance.DeviceLog.logStatus('DeviceCapture file queue flushed!', true);
                    });
                });

                /*queue.length(function(err, length) {
                    for(var i=0; i<5; i++) {
                        queue.tpop(function(err, packet, commit, rollback) {
                            ThisComponent.host.storePacket(packet)
                                .then(function() { commit(function(err) { if(err) throw err; console.log("Stored Packet uploaded");})})
                                .catch(function() { rollback(function(err) { if (err) throw err; console.log("Stored Packet Problem");})});
                        });
                    }
                });*/
            },

            startCapturing: function(device) {
                if (!pcap) return;
                if (this.isCapturing) return;   // don't do anything

                this.isCapturing = true;
                Instance.DeviceLog.logStatus('Preparing DeviceCapture...', true);

                ThisComponent.preCapture()
                .then(function() {
                    Instance.DeviceLog.logStatus('Starting DeviceCapture...', true);

                    var device = Instance.DeviceMain.getCurrentDevice();
                    var jobType = Instance.WifiSnifferDevice.DeviceJobType;
                    var pcap_session;
                    if(device.currentJobType == jobType.ActivitySniffer) {
                        pcap_session = pcap.createSession("mon0", "wlan type mgt || wlan type data");
                        pcap_session.on('packet', function(raw_packet) {
                            return Promise.resolve()
                            .then(function() {
                                var packet = pcap.decode.packet(raw_packet);
                                return ThisComponent.basicProcessor(packet);
                            });
                        });
                    }
                    else {
                        pcap_session = pcap.createSession("mon0", "wlan type mgt subtype probe-req");
                        pcap_session.on('packet', function(raw_packet) {
                            return Promise.resolve()
                            .then(function() {
                                var packet = pcap.decode.packet(raw_packet);
                                return ThisComponent.processPacket(packet);
                            })
                            .catch(function(err) {
                                Instance.DeviceLog.logError('DeviceCapture.processPacket failed  - ' + err.stack, true);
                            });
                        });
                    }
                });
            },

            /**
             * Client commands can be directly called by the host
             */
            Public: {

            }
        };
    })
});
<|endoftext|>


<commit_before>
    var   cmds = require('./cmd')
        , flagger = require('./util/flagger')
        , project = require('./project/project')
        , haxelib = require('./util/haxelib')
        , util = require('./util/util')
        , path = require('path')
        , fs = require('graceful-fs')
        , fse = require('fs-extra')

//initial setup

    project.defaults = require('./project.defaults');

var internal = {};
var flow = {
    bin_path : util.normalize(process.argv[0]),
    flow_path : util.normalize(path.dirname(process.argv[1])),
    run_path : util.normalize(process.argv[2]),
    system : util.normalize(process.argv[3]),
    quiet : {},
    log_level : 2,
    project : project,
    version : require('./package.json').version,
    config : require('./config'),
    timing : require('./config').build.timing,
    execute : function(_flow, cmd, done) {
        cmd.verify(_flow, function(err, data) {

            if(!err) {
                cmd.run(_flow, data, done);
            } else {
                cmd.error(_flow, err);
                if(done) { done(err,null); }
            }

        }); //verify
    },
    log : function(level) {
        var args = Array.prototype.slice.call(arguments,1);
        if(level <= this.log_level && this.log_level != 0) {
            if(args[0] && args[0].constructor != Object) {
                args[0] = 'flow / ' + args[0];
            }
            console.log.apply(console, args);
        }
    },
    save_user_config : function() {
        internal.save_user_config(this);
    }

};

//main command processing, called after haxelib
//async init to query paths and config

internal.run = function() {

    //store old path because we will go back
    var cwd = process.cwd();

        //builds happen in the working path
    flow.log('');
    flow.log(2, 'running in %s', flow.run_path);
    process.chdir(flow.run_path);

            //get the requested command
        var requested = flow.flags._at(0);
        var command = flow.flags._alias(requested);
            //find the command implementation
        var cmd = cmds[command];

            //check if exists
        if(cmd) {
            flow.execute(flow, cmd);
        } else {
            cmds.usage.run(flow, requested ? 'unknown command ' + requested : '');
        }

        //restore
    process.chdir(cwd);

} //run

internal.user_config_path = function(flow) {

    var home = util.normalize(util.find_home_path(flow), true);
    var config_file = '.flow.config.json';
    var abs_config = util.normalize( path.join(home, config_file) );

    return abs_config;

} //user_config_path

internal.get_user_config = function(flow) {

    var conf;

    if(fs.existsSync(flow.user_config_path)) {
        flow.log(2, 'found custom config at %s', flow.user_config_path);
        var content = fs.readFileSync(flow.user_config_path, 'utf8');
        try {
            conf = JSON.parse(content);
        } catch(e) {
            console.log('error in user config file :');
            throw e;
        }
    }

    return conf;

} //get_user_config

internal.save_user_config = function(flow) {

    fse.ensureFileSync(flow.user_config_path);
    fs.writeFileSync(flow.user_config_path, JSON.stringify(flow.user_config,null,'    '), 'utf8');

} //save_user_config

//entry point

    var args = [].concat(process.argv);
    args = args.splice(4, args.length-4);

    flow.flags = flagger.parse(args);

    if(flow.flags.log !== undefined) {
        flow.log_level = flow.flags.log;
    }

    //first check critical flags
    if(!args.length || flow.flags._has('usage')) {

        cmds.usage.run(flow, '');

    } else if((flow.flags._has('version') && args.length < 3) || flow.flags.version && args.length < 3) {

        if(!flow.flags.json) {
            console.log(flow.version);
        } else {
                //this may be redundant but might change in future
            console.log(JSON.stringify(flow.version));
        }

    } else if(flow.flags._has('er') && args.length == 1) {

        require('./util/er').er();

    } else {

        if(flow.flags._has('info')) {
            flow.log_level = 0;
        }

            //read any potential user config on top of the
            //existing config values, as these override defaults
        flow.server_path = path.join( flow.flow_path, 'tools/http-server/http-server');
        flow.user_config_path = internal.user_config_path(flow);
        flow.user_config = internal.get_user_config(flow);
        flow.config = util.merge_combine( flow.user_config, flow.config );

            //start with initing the project state values
        if(!flow.project.init(flow)) {
            return;
        }

            //useful immediate information
        flow.log(2, '%s', flow.version);
        flow.log(2, 'current platform is %s', flow.system);
        flow.log(2, 'target is %s', flow.target);

        if(flow.target != 'web'){
            flow.log(2, 'target arch is %s', flow.target_arch);
        }

            //init haxelib cache,
            //and when it's complete,
            //run the main path
        haxelib.init(flow, internal.run);

    } //non critical flags

<commit_msg>flow; add "debug is true" log note to the output for clarity<commit_after>
    var   cmds = require('./cmd')
        , flagger = require('./util/flagger')
        , project = require('./project/project')
        , haxelib = require('./util/haxelib')
        , util = require('./util/util')
        , path = require('path')
        , fs = require('graceful-fs')
        , fse = require('fs-extra')

//initial setup

    project.defaults = require('./project.defaults');

var internal = {};
var flow = {
    bin_path : util.normalize(process.argv[0]),
    flow_path : util.normalize(path.dirname(process.argv[1])),
    run_path : util.normalize(process.argv[2]),
    system : util.normalize(process.argv[3]),
    quiet : {},
    log_level : 2,
    project : project,
    version : require('./package.json').version,
    config : require('./config'),
    timing : require('./config').build.timing,
    execute : function(_flow, cmd, done) {
        cmd.verify(_flow, function(err, data) {

            if(!err) {
                cmd.run(_flow, data, done);
            } else {
                cmd.error(_flow, err);
                if(done) { done(err,null); }
            }

        }); //verify
    },
    log : function(level) {
        var args = Array.prototype.slice.call(arguments,1);
        if(level <= this.log_level && this.log_level != 0) {
            if(args[0] && args[0].constructor != Object) {
                args[0] = 'flow / ' + args[0];
            }
            console.log.apply(console, args);
        }
    },
    save_user_config : function() {
        internal.save_user_config(this);
    }

};

//main command processing, called after haxelib
//async init to query paths and config

internal.run = function() {

    //store old path because we will go back
    var cwd = process.cwd();

        //builds happen in the working path
    flow.log('');
    flow.log(2, 'running in %s', flow.run_path);
    process.chdir(flow.run_path);

            //get the requested command
        var requested = flow.flags._at(0);
        var command = flow.flags._alias(requested);
            //find the command implementation
        var cmd = cmds[command];

            //check if exists
        if(cmd) {
            flow.execute(flow, cmd);
        } else {
            cmds.usage.run(flow, requested ? 'unknown command ' + requested : '');
        }

        //restore
    process.chdir(cwd);

} //run

internal.user_config_path = function(flow) {

    var home = util.normalize(util.find_home_path(flow), true);
    var config_file = '.flow.config.json';
    var abs_config = util.normalize( path.join(home, config_file) );

    return abs_config;

} //user_config_path

internal.get_user_config = function(flow) {

    var conf;

    if(fs.existsSync(flow.user_config_path)) {
        flow.log(2, 'found custom config at %s', flow.user_config_path);
        var content = fs.readFileSync(flow.user_config_path, 'utf8');
        try {
            conf = JSON.parse(content);
        } catch(e) {
            console.log('error in user config file :');
            throw e;
        }
    }

    return conf;

} //get_user_config

internal.save_user_config = function(flow) {

    fse.ensureFileSync(flow.user_config_path);
    fs.writeFileSync(flow.user_config_path, JSON.stringify(flow.user_config,null,'    '), 'utf8');

} //save_user_config

//entry point

    var args = [].concat(process.argv);
    args = args.splice(4, args.length-4);

    flow.flags = flagger.parse(args);

    if(flow.flags.log !== undefined) {
        flow.log_level = flow.flags.log;
    }

    //first check critical flags
    if(!args.length || flow.flags._has('usage')) {

        cmds.usage.run(flow, '');

    } else if((flow.flags._has('version') && args.length < 3) || flow.flags.version && args.length < 3) {

        if(!flow.flags.json) {
            console.log(flow.version);
        } else {
                //this may be redundant but might change in future
            console.log(JSON.stringify(flow.version));
        }

    } else if(flow.flags._has('er') && args.length == 1) {

        require('./util/er').er();

    } else {

        if(flow.flags._has('info')) {
            flow.log_level = 0;
        }

            //read any potential user config on top of the
            //existing config values, as these override defaults
        flow.server_path = path.join( flow.flow_path, 'tools/http-server/http-server');
        flow.user_config_path = internal.user_config_path(flow);
        flow.user_config = internal.get_user_config(flow);
        flow.config = util.merge_combine( flow.user_config, flow.config );

            //start with initing the project state values
        if(!flow.project.init(flow)) {
            return;
        }

            //useful immediate information
        flow.log(2, '%s', flow.version);
        flow.log(2, 'current platform is %s', flow.system);
        flow.log(2, 'target is %s', flow.target);

        if(flow.target != 'web'){
            flow.log(2, 'target arch is %s', flow.target_arch);
        }

        if(flow.flags.debug) {
            flow.log(2, 'debug is true');
        }
            //init haxelib cache,
            //and when it's complete,
            //run the main path
        haxelib.init(flow, internal.run);

    } //non critical flags

<|endoftext|>


<commit_before>/*
 * Copyright 2018 Expedia, Inc.
 *
 *         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.
 */

const axios = require('axios');
const Q = require('q');
const errorConverter = require('../utils/errorConverter');
const logger = require('../../utils/logger').withIdentifier('fetcher');
const metrics = require('../../utils/metrics');

const fetcher = fetcherName => ({
        fetch: (url) => {
            const deferred = Q.defer();
            const timer = metrics.timer(`fetcher_${fetcherName}`).start();

            axios
            .get(url)
            .then((response) => {
                timer.end();
                logger.info(`fetch successful: ${url}`);
                deferred.resolve(response.data);
            }, (error) => {
                timer.end();
                logger.error(`fetch failed: ${url}`);
                deferred.reject(errorConverter.fromAxiosError(error));
            });

            return deferred.promise;
        }
    });

module.exports = fetcher;
<commit_msg>adding failure meter for REST fetcher<commit_after>/*
 * Copyright 2018 Expedia, Inc.
 *
 *         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.
 */

const axios = require('axios');
const Q = require('q');
const errorConverter = require('../utils/errorConverter');
const logger = require('../../utils/logger').withIdentifier('fetcher.rest');
const metrics = require('../../utils/metrics');

const fetcher = fetcherName => ({
        fetch: (url) => {
            const deferred = Q.defer();
            const timer = metrics.timer(`fetcher_rest_${fetcherName}`).start();

            axios
            .get(url)
            .then((response) => {
                timer.end();
                logger.info(`fetch successful: ${url}`);

                deferred.resolve(response.data);
            }, (error) => {
                timer.end();
                metrics.meter(`fetcher_rest_failure_${fetcherName}`).mark();
                logger.error(`fetch failed: ${url}`);

                deferred.reject(errorConverter.fromAxiosError(error));
            });

            return deferred.promise;
        }
    });

module.exports = fetcher;
<|endoftext|>


<commit_before>const _ = require('underscore');
const DrawCard = require('../../drawcard.js');

class ShibaTsukune extends DrawCard {
    setupCardAbilities() {
        this.interrupt({
            title: 'Resolve 2 rings',
            when : {
                onPhaseEnded: event => event.phase === 'conflict'
            },
            effect: 'resolve up to 2 ring effects',
            handler: context => this.game.promptForRingSelect(context.player, {
                activePromptTitle: 'Choose a ring to resolve',
                context: context,
                ringCondition: ring => !ring.claimed,
                onSelect: (player, firstRing) => {
                    if(_.size(_.filter(this.game.rings, ring => !ring.claimed)) > 1) {
                        this.game.promptForRingSelect(player, {
                            activePromptTitle: 'Choose a second ring to resolve, or click Done',
                            ringCondition: ring => !ring.claimed && ring !== firstRing,
                            context: context,
                            optional: true,
                            onMenuCommand: player => {
                                this.game.addMessage('{0} resolves {1}', player, firstRing);
                                let event = this.game.actions.resolveRingEffect().getEvent(firstRing, this.game.getFrameworkContext(player));
                                this.game.openThenEventWindow(event);
                                return true;
                            },
                            onSelect: (player, secondRing) => {
                                this.game.addMessage('{0} resolves {1}', player, [firstRing, secondRing]);
                                let events = [firstRing, secondRing].map(ring =>
                                    this.game.actions.resolveRingEffect().getEvent(ring, this.game.getFrameworkContext(player)));
                                this.game.openThenEventWindow(events);
                                return true;
                            }
                        });
                    } else {
                        this.game.addMessage('{0} resolves {1}', context.player, firstRing);
                        let event = this.game.actions.resolveRingEffect().getEvent(firstRing, this.game.getFrameworkContext(player));
                        this.game.openThenEventWindow(event);
                    }
                    return true;
                }
            })
        });
    }
}

ShibaTsukune.id = 'shiba-tsukune';

module.exports = ShibaTsukune;
<commit_msg>Fix Tsukune to resolve rings simultaneously<commit_after>const _ = require('underscore');
const DrawCard = require('../../drawcard.js');

class ShibaTsukune extends DrawCard {
    setupCardAbilities() {
        this.interrupt({
            title: 'Resolve 2 rings',
            when : {
                onPhaseEnded: event => event.phase === 'conflict'
            },
            effect: 'resolve up to 2 ring effects',
            handler: context => this.game.promptForRingSelect(context.player, {
                activePromptTitle: 'Choose a ring to resolve',
                context: context,
                ringCondition: ring => !ring.claimed,
                onSelect: (player, firstRing) => {
                    if(_.size(_.filter(this.game.rings, ring => !ring.claimed)) > 1) {
                        this.game.promptForRingSelect(player, {
                            activePromptTitle: 'Choose a second ring to resolve, or click Done',
                            ringCondition: ring => !ring.claimed && ring !== firstRing,
                            context: context,
                            optional: true,
                            onMenuCommand: player => {
                                this.game.addMessage('{0} resolves {1}', player, firstRing);
                                let event = this.game.actions.resolveRingEffect().getEvent(firstRing, this.game.getFrameworkContext(player));
                                this.game.openThenEventWindow(event);
                                return true;
                            },
                            onSelect: (player, secondRing) => {
                                this.game.addMessage('{0} resolves {1}', player, [firstRing, secondRing]);
                                let action = this.game.actions.resolveRingEffect();
                                action.setTarget([firstRing, secondRing]);
                                this.game.openThenEventWindow(action.getEventArray(this.game.getFrameworkContext(player)));
                                return true;
                            }
                        });
                    } else {
                        this.game.addMessage('{0} resolves {1}', context.player, firstRing);
                        let event = this.game.actions.resolveRingEffect().getEvent(firstRing, this.game.getFrameworkContext(player));
                        this.game.openThenEventWindow(event);
                    }
                    return true;
                }
            })
        });
    }
}

ShibaTsukune.id = 'shiba-tsukune';

module.exports = ShibaTsukune;
<|endoftext|>


<commit_before>/**
Internal resume generation logic for FluentCV.
@license MIT. Copyright (c) 2015 James M. Devlin / FluentDesk
*/

module.exports = function () {

  // We don't mind pseudo-globals here
  var path = require( 'path' )
    , extend = require( './utils/extend' )
    , unused = require('./utils/string')
    , FS = require('fs')
    , _ = require('underscore')
    , FLUENT = require('./fluentlib')
    , PATH = require('path')
    , MKDIRP = require('mkdirp')
    , rez, _log, _err;

  /**
  Given a source JSON resume, a destination resume path, and a theme file,
  generate 0..N resumes in the desired formats.
  @param src Path to the source JSON resume file: "rez/resume.json".
  @param dst An array of paths to the target resume file(s).
  @param theme Friendly name of the resume theme. Defaults to "modern".
  @param logger Optional logging override.
  */
  function gen( src, dst, opts, logger, errHandler ) {

    _log = logger || console.log;
    _err = errHandler || error;

    //_opts = extend( true, _opts, opts );
    _opts.theme = (opts.theme && opts.theme.toLowerCase().trim()) || 'modern';
    _opts.prettify = opts.prettify === true ? _opts.prettify : false;

    // Load input resumes...
    if(!src || !src.length) { throw { fluenterror: 3 }; }
    var sheets = src.map( function( res ) {
      _log( 'Reading JSON resume: ' + res );
      return (new FLUENT.FRESHResume()).open( res );
    });

    // Merge input resumes...
    var msg = '';
    rez = _.reduceRight( sheets, function( a, b, idx ) {
      msg += ((idx == sheets.length - 2) ? 'Merging ' + a.meta.fileName : '')
        + ' onto ' + b.meta.fileName;
      return extend( true, b, a );
    });
    msg && _log(msg);

    // Load the active theme
    // Verify the specified theme name/path
    var tFolder = PATH.resolve( __dirname, '../node_modules/fluent-themes/themes', _opts.theme );
    var exists = require('./utils/file-exists');
    if (!exists( tFolder )) {
      tFolder = PATH.resolve( _opts.theme );
      if (!exists( tFolder )) {
        throw { fluenterror: 1, data: _opts.theme };
      }
    }
    var theTheme = new FLUENT.Theme().open( tFolder );
    _opts.themeObj = theTheme;
    _log( 'Applying ' + theTheme.name.toUpperCase() + ' theme (' + Object.keys(theTheme.formats).length + ' formats)' );

    // Expand output resumes... (can't use map() here)
    var targets = [];
    var that = this;
    ( (dst && dst.length && dst) || ['resume.all'] ).forEach( function(t) {
      var to = path.resolve(t), pa = path.parse(to), fmat = pa.ext || '.all';
      targets.push.apply(targets, fmat === '.all' ?
        Object.keys( theTheme.formats ).map(function(k){ var z = theTheme.formats[k]; return { file: to.replace(/all$/g,z.pre), fmt: z } })
        : [{ file: to, fmt: theTheme.getFormat( fmat.slice(1) ) }]);
    });

    // Run the transformation!
    var finished = targets.map( function(t) { return single(t, theTheme); } );

    // Don't send the client back empty-handed
    return { sheet: rez, targets: targets, processed: finished };
  }

  /**
  Generate a single resume of a specific format.
  @param f Full path to the destination resume to generate, for example,
  "/foo/bar/resume.pdf" or "c:\foo\bar\resume.txt".
  */
  function single( fi, theme ) {
    try {
      var f = fi.file, fType = fi.fmt.ext, fName = path.basename( f, '.' + fType );
      var fObj = _.property( fi.fmt.pre )( theme.formats );
      var fOut = path.join( f.substring( 0, f.lastIndexOf('.') + 1 ) + fObj.pre );
      _log( 'Generating ' + fi.fmt.title.toUpperCase() + ' resume: ' + path.relative(process.cwd(), f ) );
      var theFormat = _fmts.filter( function( fmt ) {
        return fmt.name === fi.fmt.pre;
      })[0];
      MKDIRP( path.dirname(fOut) ); // Ensure dest folder exists; don't bug user
      theFormat.gen.generate( rez, fOut, _opts );
    }
    catch( ex ) {
      _err( ex );
    }
  }

  /**
  Handle an exception.
  */
  function error( ex ) {
    throw ex;
  }

  /**
  Validate 1 to N resumes as vanilla JSON.
  */
  // function validateAsJSON( src, logger ) {
  //   _log = logger || console.log;
  //   if( !src || !src.length ) { throw { fluenterror: 3 }; }
  //   var isValid = true;
  //   var sheets = src.map( function( res ) {
  //     try {
  //       var rawJson = FS.readFileSync( res, 'utf8' );
  //       var testObj = JSON.parse( rawJson );
  //     }
  //     catch(ex) {
  //       if (!(ex instanceof SyntaxError)) { throw ex; } // [1]
  //       isValid = false;
  //     }
  //
  //     _log( 'Validating JSON resume: ' + res + (isValid ? ' (VALID)' : ' (INVALID)'));
  //     return isValid;
  //   });
  // }

  /**
  Validate 1 to N resumes in either FRESH or JSON Resume format.
  */
  function validate( src, unused, opts, logger ) {
    _log = logger || console.log;
    if( !src || !src.length ) { throw { fluenterror: 3 }; }
    var isValid = true;
    var sheets = src.map( function( res ) {
      var sheet = (new FLUENT.FRESHResume()).open( res );
      var valid = sheet.isValid();
      _log( 'Validating JSON resume: ' + res +
        (valid ? ' (VALID)' : ' (INVALID)'));
      if( !valid ) {
        _log( sheet.meta.validationErrors );
      }
    });
  }

  /**
  Supported resume formats.
  */
  var _fmts = [
    { name: 'html', ext: 'html', gen: new FLUENT.HtmlGenerator() },
    { name: 'txt',  ext: 'txt', gen: new FLUENT.TextGenerator()  },
    { name: 'doc',  ext: 'doc',  fmt: 'xml', gen: new FLUENT.WordGenerator() },
    { name: 'pdf',  ext: 'pdf', fmt: 'html', is: false, gen: new FLUENT.HtmlPdfGenerator() },
    { name: 'md', ext: 'md', fmt: 'txt', gen: new FLUENT.MarkdownGenerator() },
    { name: 'json', ext: 'json', gen: new FLUENT.JsonGenerator() },
    { name: 'yml', ext: 'yml', fmt: 'yml', gen: new FLUENT.JsonYamlGenerator() }
  ];

  /**
  Default FluentCV options.
  */
  var _opts = {
    theme: 'modern',
    prettify: { // ← See https://github.com/beautify-web/js-beautify#options
      indent_size: 2,
      unformatted: ['em','strong'],
      max_char: 80, // ← See lib/html.js in above-linked repo
      //wrap_line_length: 120, ← Don't use this
    }
  };

  /**
  Internal module interface. Used by FCV Desktop and HMR.
  */
  return {
    verbs: {
      generate: gen,
      validate: validate,
      convert: convert
    },
    lib: require('./fluentlib'),
    options: _opts,
    formats: _fmts
  };

}();

// [1]: JSON.parse throws SyntaxError on invalid JSON. See:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
<commit_msg>Remove unused verb.<commit_after>/**
Internal resume generation logic for FluentCV.
@license MIT. Copyright (c) 2015 James M. Devlin / FluentDesk
*/

module.exports = function () {

  // We don't mind pseudo-globals here
  var path = require( 'path' )
    , extend = require( './utils/extend' )
    , unused = require('./utils/string')
    , FS = require('fs')
    , _ = require('underscore')
    , FLUENT = require('./fluentlib')
    , PATH = require('path')
    , MKDIRP = require('mkdirp')
    , rez, _log, _err;

  /**
  Given a source JSON resume, a destination resume path, and a theme file,
  generate 0..N resumes in the desired formats.
  @param src Path to the source JSON resume file: "rez/resume.json".
  @param dst An array of paths to the target resume file(s).
  @param theme Friendly name of the resume theme. Defaults to "modern".
  @param logger Optional logging override.
  */
  function gen( src, dst, opts, logger, errHandler ) {

    _log = logger || console.log;
    _err = errHandler || error;

    //_opts = extend( true, _opts, opts );
    _opts.theme = (opts.theme && opts.theme.toLowerCase().trim()) || 'modern';
    _opts.prettify = opts.prettify === true ? _opts.prettify : false;

    // Load input resumes...
    if(!src || !src.length) { throw { fluenterror: 3 }; }
    var sheets = src.map( function( res ) {
      _log( 'Reading JSON resume: ' + res );
      return (new FLUENT.FRESHResume()).open( res );
    });

    // Merge input resumes...
    var msg = '';
    rez = _.reduceRight( sheets, function( a, b, idx ) {
      msg += ((idx == sheets.length - 2) ? 'Merging ' + a.meta.fileName : '')
        + ' onto ' + b.meta.fileName;
      return extend( true, b, a );
    });
    msg && _log(msg);

    // Load the active theme
    // Verify the specified theme name/path
    var tFolder = PATH.resolve( __dirname, '../node_modules/fluent-themes/themes', _opts.theme );
    var exists = require('./utils/file-exists');
    if (!exists( tFolder )) {
      tFolder = PATH.resolve( _opts.theme );
      if (!exists( tFolder )) {
        throw { fluenterror: 1, data: _opts.theme };
      }
    }
    var theTheme = new FLUENT.Theme().open( tFolder );
    _opts.themeObj = theTheme;
    _log( 'Applying ' + theTheme.name.toUpperCase() + ' theme (' + Object.keys(theTheme.formats).length + ' formats)' );

    // Expand output resumes... (can't use map() here)
    var targets = [];
    var that = this;
    ( (dst && dst.length && dst) || ['resume.all'] ).forEach( function(t) {
      var to = path.resolve(t), pa = path.parse(to), fmat = pa.ext || '.all';
      targets.push.apply(targets, fmat === '.all' ?
        Object.keys( theTheme.formats ).map(function(k){ var z = theTheme.formats[k]; return { file: to.replace(/all$/g,z.pre), fmt: z } })
        : [{ file: to, fmt: theTheme.getFormat( fmat.slice(1) ) }]);
    });

    // Run the transformation!
    var finished = targets.map( function(t) { return single(t, theTheme); } );

    // Don't send the client back empty-handed
    return { sheet: rez, targets: targets, processed: finished };
  }

  /**
  Generate a single resume of a specific format.
  @param f Full path to the destination resume to generate, for example,
  "/foo/bar/resume.pdf" or "c:\foo\bar\resume.txt".
  */
  function single( fi, theme ) {
    try {
      var f = fi.file, fType = fi.fmt.ext, fName = path.basename( f, '.' + fType );
      var fObj = _.property( fi.fmt.pre )( theme.formats );
      var fOut = path.join( f.substring( 0, f.lastIndexOf('.') + 1 ) + fObj.pre );
      _log( 'Generating ' + fi.fmt.title.toUpperCase() + ' resume: ' + path.relative(process.cwd(), f ) );
      var theFormat = _fmts.filter( function( fmt ) {
        return fmt.name === fi.fmt.pre;
      })[0];
      MKDIRP( path.dirname(fOut) ); // Ensure dest folder exists; don't bug user
      theFormat.gen.generate( rez, fOut, _opts );
    }
    catch( ex ) {
      _err( ex );
    }
  }

  /**
  Handle an exception.
  */
  function error( ex ) {
    throw ex;
  }

  /**
  Validate 1 to N resumes as vanilla JSON.
  */
  // function validateAsJSON( src, logger ) {
  //   _log = logger || console.log;
  //   if( !src || !src.length ) { throw { fluenterror: 3 }; }
  //   var isValid = true;
  //   var sheets = src.map( function( res ) {
  //     try {
  //       var rawJson = FS.readFileSync( res, 'utf8' );
  //       var testObj = JSON.parse( rawJson );
  //     }
  //     catch(ex) {
  //       if (!(ex instanceof SyntaxError)) { throw ex; } // [1]
  //       isValid = false;
  //     }
  //
  //     _log( 'Validating JSON resume: ' + res + (isValid ? ' (VALID)' : ' (INVALID)'));
  //     return isValid;
  //   });
  // }

  /**
  Validate 1 to N resumes in either FRESH or JSON Resume format.
  */
  function validate( src, unused, opts, logger ) {
    _log = logger || console.log;
    if( !src || !src.length ) { throw { fluenterror: 3 }; }
    var isValid = true;
    var sheets = src.map( function( res ) {
      var sheet = (new FLUENT.FRESHResume()).open( res );
      var valid = sheet.isValid();
      _log( 'Validating JSON resume: ' + res +
        (valid ? ' (VALID)' : ' (INVALID)'));
      if( !valid ) {
        _log( sheet.meta.validationErrors );
      }
    });
  }

  /**
  Supported resume formats.
  */
  var _fmts = [
    { name: 'html', ext: 'html', gen: new FLUENT.HtmlGenerator() },
    { name: 'txt',  ext: 'txt', gen: new FLUENT.TextGenerator()  },
    { name: 'doc',  ext: 'doc',  fmt: 'xml', gen: new FLUENT.WordGenerator() },
    { name: 'pdf',  ext: 'pdf', fmt: 'html', is: false, gen: new FLUENT.HtmlPdfGenerator() },
    { name: 'md', ext: 'md', fmt: 'txt', gen: new FLUENT.MarkdownGenerator() },
    { name: 'json', ext: 'json', gen: new FLUENT.JsonGenerator() },
    { name: 'yml', ext: 'yml', fmt: 'yml', gen: new FLUENT.JsonYamlGenerator() }
  ];

  /**
  Default FluentCV options.
  */
  var _opts = {
    theme: 'modern',
    prettify: { // ← See https://github.com/beautify-web/js-beautify#options
      indent_size: 2,
      unformatted: ['em','strong'],
      max_char: 80, // ← See lib/html.js in above-linked repo
      //wrap_line_length: 120, ← Don't use this
    }
  };

  /**
  Internal module interface. Used by FCV Desktop and HMR.
  */
  return {
    verbs: {
      generate: gen,
      validate: validate
    },
    lib: require('./fluentlib'),
    options: _opts,
    formats: _fmts
  };

}();

// [1]: JSON.parse throws SyntaxError on invalid JSON. See:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
<|endoftext|>


<commit_before>const _ = require('underscore');

const DrawCard = require('../../drawcard.js');

class VaesDothrak extends DrawCard {
    setupCardAbilities(ability) {
        this.reaction({
            when: {
                onPlotsRevealed: () => this.hasPossibleLegalTarget()
            },
            cost: ability.costs.discardFromHand(card => card.getType() === 'attachment'),
            handler: context => {
                this.game.promptForSelect(this.controller, {
                    activePromptTitle: 'Select an attachment',
                    source: this,
                    cardCondition: card => (
                        card.location === 'play area' &&
                        card.getType() === 'attachment' &&
                        card.getCost(true) <= context.costs.discardFromHand.getCost(true)),
                    onSelect: (p, card) => {
                        card.controller.discardCard(card);
                        this.game.addMessage('{0} uses {1} and discards {2} from their hand to discard {3} from play',
                            this.controller, this, context.costs.discardFromHand, card);

                        return true;
                    }
                });
            }
        });
    }

    hasPossibleLegalTarget() {
        let attachmentsInHand = this.controller.findCards(this.controller.hand, card => card.getType() === 'attachment');
        let attachmentsInHandCosts = _.map(attachmentsInHand, card => card.getCost(true));
        let attachmentsInHandHighestCost = _.max(attachmentsInHandCosts);

        let attachmentsInPlay = this.game.findAnyCardsInPlay(card => card.getType() === 'attachment');
        let attachmentsInPlayCosts = _.map(attachmentsInPlay, card => card.getCost(true));
        let attachmentsInPlayLowestCost = _.min(attachmentsInPlayCosts);

        return attachmentsInHandHighestCost >= attachmentsInPlayLowestCost;
    }
}

VaesDothrak.code = '02014';

module.exports = VaesDothrak;
<commit_msg>Fixes to Vaes Dothrak (#1949)<commit_after>const DrawCard = require('../../drawcard.js');

class VaesDothrak extends DrawCard {
    setupCardAbilities(ability) {
        this.reaction({
            when: {
                onPlotsRevealed: event => event.plots.some(plot => plot.controller === this.controller)
            },
            cost: ability.costs.discardFromHand(card => card.getType() === 'attachment' && this.hasPossibleLegalTarget(card)),
            target: {
                activePromptTitle: 'Select an attachment',
                cardCondition: (card, context) => !context.costs.discardFromHand || this.isValidTarget(card, context.costs.discardFromHand)
            },
            handler: context => {
                let card = context.target;
                card.controller.discardCard(card);
                this.game.addMessage('{0} uses {1} and discards {2} from their hand to discard {3} from play',
                    this.controller, this, context.costs.discardFromHand, card);
            }
        });
    }

    hasPossibleLegalTarget(inHandAttachment) {
        return this.game.anyCardsInPlay(card => this.isValidTarget(card, inHandAttachment));
    }

    isValidTarget(card, inHandAttachment) {
        return card.location === 'play area' && card.getType() === 'attachment' && card.getPrintedCost() <= inHandAttachment.getPrintedCost();
    }
}

VaesDothrak.code = '02014';

module.exports = VaesDothrak;
<|endoftext|>


<commit_before>/*
Copyright [2016] [Relevance Lab]

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

var mongoose = require('mongoose');
var ObjectId = require('mongoose').Types.ObjectId;
var validate = require('mongoose-validator');
var logger = require('_pr/logger')(module);
var schemaValidator = require('../../dao/schema-validator');

var Schema = mongoose.Schema;

var taskHistorySchema = new Schema({
    taskId: String,
    taskType: String,
    runlist: [String],
    nodeIds: [String],
    nodeIdsWithActionLog: [{
        nodeId: String,
        actionLogId: String
    }],
    attributes: Schema.Types.Mixed,
    jenkinsServerId: String,
    jobName: String,
    buildNumber: Number,
    previousBuildNumber: Number,
    status: String,
    user: String,
    timestampStarted: Number,
    timestampEnded: Number,
    jobResultURL: [String],
    executionResults: [Schema.Types.Mixed],
    assignedTaskIds: [String],
    taskHistoryIds: [{
        taskId: String,
        historyId: String
    }],

    blueprintExecutionResults: Schema.Types.Mixed
});

taskHistorySchema.method.update = function(status, timestampEnded, callback) {
    var self = this;
    var taskHistory = new self(historyData);

    taskHistory.save(function(err, tHistory) {
        if (err) {
            callback(err, null);
            return;
        }
        callback(null, tHistory);
    });
};

taskHistorySchema.statics.createNew = function(historyData, callback) {
    var self = this;
    var taskHistory = new self(historyData);

    taskHistory.save(function(err, tHistory) {
        logger.debug('saving task history ==>');
        if (err) {
            callback(err, null);
            return;
        }
        callback(null, tHistory);
    });
};

taskHistorySchema.statics.getHistoryByTaskId = function(taskId, callback) {
    this.find({
        $query: {
            taskId: taskId
        },
        $orderby: {
            "buildNumber": -1
    }, function(err, tHistories) {
        if (err) {
            callback(err, null);
            return;
        }
        callback(null, tHistories);
    });
};

taskHistorySchema.statics.getHistoryByTaskIdAndHistoryId = function(taskId, historyId, callback) {
    this.find({
        taskId: taskId,
        _id: new ObjectId(historyId)
    }, function(err, tHistories) {
        if (err) {
            callback(err, null);
            return;
        }
        if (tHistories.length) {
            callback(null, tHistories[0]);
        } else {
            callback(null, null);
        }
    });
};

taskHistorySchema.statics.getLast100HistoriesByTaskId = function(taskId, callback) {

    this.find({
        taskId: taskId
    }, function(err, tHistories) {
        if (err) {
            callback(err, null);
            return;
        }
        callback(null, tHistories);
    }).sort({
        buildNumber: -1
    }).limit(100);
};

taskHistorySchema.statics.listHistory = function(callback) {

    this.find(function(err, tHistories) {
        if (err) {
            callback(err, null);
            return;
        }
        callback(null, tHistories);
    });
};

var TaskHistory = mongoose.model('taskHistory', taskHistorySchema);

module.exports = TaskHistory;
<commit_msg>fixed synxtax error<commit_after>/*
Copyright [2016] [Relevance Lab]

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

var mongoose = require('mongoose');
var ObjectId = require('mongoose').Types.ObjectId;
var validate = require('mongoose-validator');
var logger = require('_pr/logger')(module);
var schemaValidator = require('../../dao/schema-validator');

var Schema = mongoose.Schema;

var taskHistorySchema = new Schema({
	taskId: String,
	taskType: String,
	runlist: [String],
	nodeIds: [String],
	nodeIdsWithActionLog: [{
		nodeId: String,
		actionLogId: String
	}],
	attributes: Schema.Types.Mixed,
	jenkinsServerId: String,
	jobName: String,
	buildNumber: Number,
	previousBuildNumber: Number,
	status: String,
	user: String,
	timestampStarted: Number,
	timestampEnded: Number,
	jobResultURL: [String],
	executionResults: [Schema.Types.Mixed],
	assignedTaskIds: [String],
	taskHistoryIds: [{
		taskId: String,
		historyId: String
	}],

	blueprintExecutionResults: Schema.Types.Mixed
});

taskHistorySchema.method.update = function(status, timestampEnded, callback) {
	var self = this;
	var taskHistory = new self(historyData);

	taskHistory.save(function(err, tHistory) {
		if (err) {
			callback(err, null);
			return;
		}
		callback(null, tHistory);
	});
};

taskHistorySchema.statics.createNew = function(historyData, callback) {
	var self = this;
	var taskHistory = new self(historyData);

	taskHistory.save(function(err, tHistory) {
		logger.debug('saving task history ==>');
		if (err) {
			callback(err, null);
			return;
		}
		callback(null, tHistory);
	});
};

taskHistorySchema.statics.getHistoryByTaskId = function(taskId, callback) {
	this.find({
		$query: {
			taskId: taskId
		},
		$orderby: {
			"buildNumber": -1
		}
	}, function(err, tHistories) {
		if (err) {
			callback(err, null);
			return;
		}
		callback(null, tHistories);
	});
};

taskHistorySchema.statics.getHistoryByTaskIdAndHistoryId = function(taskId, historyId, callback) {
	this.find({
		taskId: taskId,
		_id: new ObjectId(historyId)
	}, function(err, tHistories) {
		if (err) {
			callback(err, null);
			return;
		}
		if (tHistories.length) {
			callback(null, tHistories[0]);
		} else {
			callback(null, null);
		}
	});
};

taskHistorySchema.statics.getLast100HistoriesByTaskId = function(taskId, callback) {

	this.find({
		taskId: taskId
	}, function(err, tHistories) {
		if (err) {
			callback(err, null);
			return;
		}
		callback(null, tHistories);
	}).sort({
		buildNumber: -1
	}).limit(100);
};

taskHistorySchema.statics.listHistory = function(callback) {

	this.find(function(err, tHistories) {
		if (err) {
			callback(err, null);
			return;
		}
		callback(null, tHistories);
	});
};

var TaskHistory = mongoose.model('taskHistory', taskHistorySchema);

module.exports = TaskHistory;<|endoftext|>