<commit_before>// Load in dependencies
var assert = require('assert');
var fs = require('fs');
var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
var _ = require('underscore');
var async = require('async');
var imageDiff = require('image-diff');
var rimraf = require('rimraf');
var shellQuote = require('shell-quote');
var serverUtils = require('../utils/server');

// TODO: Before landing, re-enable canvas removal (causes timing issues)

// Set up common variables
var expectedScreenshots = __dirname + '/expected_screenshots';
var actualScreenshots = __dirname + '/actual_screenshots';
var diffScreenshots = __dirname + '/diff_screenshots';

// Clean up actual screenshots and diffs
rimraf.sync(actualScreenshots);
rimraf.sync(diffScreenshots);

// Ensure the screenshot diff directory exists
fs.mkdirSync(diffScreenshots);

// Set up unabstracted variables
// TODO: Move browsers, urls into standalone files
// TODO: See notes in https://gist.github.com/twolfson/6077989
// TODO: Optimize space via tarballing expected files?
// var browsers = ['phantomjs'];
// DEV: js-yaml is required to make this require work properly
var yml = require('js-yaml');
var urls = require('./urls.yml');
assert(yml); // DEV: We use assert to silence jshint complaints

// Start a server
var server = serverUtils.startServer();

// Start up Xvfb
var DISPLAY = ':99';
var xvfbChild = spawn('Xvfb', [DISPLAY]);

// Collect xvfb stdout and stderr
var xvfbStdout = '';
var xvfbStderr = '';
xvfbChild.stdout.on('data', function addStdout (buff) {
  xvfbStdout += buff;
});
xvfbChild.stderr.on('data', function addStderr (buff) {
  xvfbStderr += buff;
});

// If xvfb terminates
xvfbChild.on('exit', function handleXvfbPrematureExit (code) {
  console.error('Xvfb exited early', code);
  console.error('XVFB STDOUT:', xvfbStdout);
  console.error('XVFB STDERR:', xvfbStderr);
  process.exit(1);
});

// For each of the URLs
async.map(urls, function (pathname, done) {
  // Screenshot the webpage
  var url = serverUtils.getUrl(pathname);
  var filename = encodeURIComponent(pathname) + '.png';
  var actualImg = actualScreenshots + '/' + filename;
  var screenshotCmd = shellQuote.quote(['nw', '.', url, actualImg]);
  exec(screenshotCmd, {
    cwd: __dirname + '/node-webkit_scripts/',
    env: _.defaults({
      DISPLAY: DISPLAY
    }, process.env)
  }, function processScreenshot (err, stdout, stderr) {
    // If stderr or stdout exist, log them
    if (stderr) { console.log('NODE-WEBKIT STDERR: ', stderr); }
    if (stdout) { console.log('NODE-WEBKIT STDOUT: ', stdout); }

    // If there is an error, callback with it
    if (err) { return done(err); }

    // TODO: Emit an event instead
    // Notify the user that we have screenshotted successfully
    console.log('Successfully screenshotted ' + url);

    imageDiff({
      actualImage: actualImg,
      expectedImage: expectedScreenshots + '/' + filename,
      diffImage: diffScreenshots + '/' + filename
    }, function handleDiffResult (err, imagesAreSame) {
      // If there was an error, callback with it
      if (err) { return done(err); }

      // Otherwise, callback with result
      done(null, {
        url: url,
        pass: imagesAreSame
      });
    });
  });
}, function (err, results) {
  // Stop Xvfb
  xvfbChild.kill();
  xvfbChild.removeAllListeners('exit');
  xvfbChild.on('exit', function handleXvfbExit () {
    // Take down server
    server.destroy(function handleServerExit () {
      // If there was an error, log it and leave
      if (err) {
        console.error('SERVER-DESTROY ERROR: ', err);
        return process.exit(1);
      }

      // Otherwise, determine if there were any failures
      var failedResults = results.filter(function (result) {
        return !result.pass;
      });

      // If there were failures, log them and leave
      if (failedResults.length > 0) {
        failedResults.forEach(function (result) {
          console.log('Failed result for ' + result.url);
        });
        process.exit(1);
      } else {
      // Otherwise, exit gracefully
        console.log('All done!');
        process.exit(0);
      }
    });
  });
});
<commit_msg>Filtering error noise<commit_after>// Load in dependencies
var assert = require('assert');
var fs = require('fs');
var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
var _ = require('underscore');
var async = require('async');
var imageDiff = require('image-diff');
var rimraf = require('rimraf');
var shellQuote = require('shell-quote');
var serverUtils = require('../utils/server');

// TODO: Before landing, re-enable canvas removal (causes timing issues)

// Set up common variables
var expectedScreenshots = __dirname + '/expected_screenshots';
var actualScreenshots = __dirname + '/actual_screenshots';
var diffScreenshots = __dirname + '/diff_screenshots';

// Clean up actual screenshots and diffs
rimraf.sync(actualScreenshots);
rimraf.sync(diffScreenshots);

// Ensure the screenshot diff directory exists
fs.mkdirSync(diffScreenshots);

// Set up unabstracted variables
// TODO: Move browsers, urls into standalone files
// TODO: See notes in https://gist.github.com/twolfson/6077989
// TODO: Optimize space via tarballing expected files?
// var browsers = ['phantomjs'];
// DEV: js-yaml is required to make this require work properly
var yml = require('js-yaml');
var urls = require('./urls.yml');
assert(yml); // DEV: We use assert to silence jshint complaints

// Start a server
var server = serverUtils.startServer();

// Start up Xvfb
var DISPLAY = ':99';
var xvfbChild = spawn('Xvfb', [DISPLAY]);

// Collect xvfb stdout and stderr
var xvfbStdout = '';
var xvfbStderr = '';
xvfbChild.stdout.on('data', function addStdout (buff) {
  xvfbStdout += buff;
});
xvfbChild.stderr.on('data', function addStderr (buff) {
  xvfbStderr += buff;
});

// If xvfb terminates
xvfbChild.on('exit', function handleXvfbPrematureExit (code) {
  console.error('Xvfb exited early', code);
  console.error('XVFB STDOUT:', xvfbStdout);
  console.error('XVFB STDERR:', xvfbStderr);
  process.exit(1);
});

// For each of the URLs
async.map(urls, function (pathname, done) {
  // Screenshot the webpage
  var url = serverUtils.getUrl(pathname);
  var filename = encodeURIComponent(pathname) + '.png';
  var actualImg = actualScreenshots + '/' + filename;
  var screenshotCmd = shellQuote.quote(['nw', '.', url, actualImg]);
  exec(screenshotCmd, {
    cwd: __dirname + '/node-webkit_scripts/',
    env: _.defaults({
      DISPLAY: DISPLAY
    }, process.env)
  }, function processScreenshot (err, stdout, stderr) {
    // If stderr or stdout exist, log them
    if (stderr) {
      console.log('NODE-WEBKIT STDERR: ', stderr.split(/\n/g).filter(function removeCommon (line) {
        return !line.match(/process_singleton_linux.cc/);
      }).join('\n'));
    }
    if (stdout) { console.log('NODE-WEBKIT STDOUT: ', stdout); }

    // If there is an error, callback with it
    if (err) { return done(err); }

    // TODO: Emit an event instead
    // Notify the user that we have screenshotted successfully
    console.log('Successfully screenshotted ' + url);

    imageDiff({
      actualImage: actualImg,
      expectedImage: expectedScreenshots + '/' + filename,
      diffImage: diffScreenshots + '/' + filename
    }, function handleDiffResult (err, imagesAreSame) {
      // If there was an error, callback with it
      if (err) { return done(err); }

      // Otherwise, callback with result
      done(null, {
        url: url,
        pass: imagesAreSame
      });
    });
  });
}, function (err, results) {
  // Stop Xvfb
  xvfbChild.kill();
  xvfbChild.removeAllListeners('exit');
  xvfbChild.on('exit', function handleXvfbExit () {
    // Take down server
    server.destroy(function handleServerExit () {
      // If there was an error, log it and leave
      if (err) {
        console.error('SERVER-DESTROY ERROR: ', err);
        return process.exit(1);
      }

      // Otherwise, determine if there were any failures
      var failedResults = results.filter(function (result) {
        return !result.pass;
      });

      // If there were failures, log them and leave
      if (failedResults.length > 0) {
        failedResults.forEach(function (result) {
          console.log('Failed result for ' + result.url);
        });
        process.exit(1);
      } else {
      // Otherwise, exit gracefully
        console.log('All done!');
        process.exit(0);
      }
    });
  });
});
<|endoftext|>


<commit_before>dojo.provide("dijit.util.parser");

dojo.require("dijit.util.manager");
dojo.require("dojo.date.serial");

dijit.util.parser = new function(){

	function val2type(/*Object*/ value){
		// summary:
		//	Returns name of type of given value.
		//	Like dojo.lang but more types.

		if(dojo.isString(value)){ return "string"; }
		if(typeof value == "number"){ return "number"; }
		if(typeof value == "boolean"){ return "boolean"; }
		if(dojo.isFunction(value)){ return "function"; }
		if(dojo.isArray(value)){ return "array"; } // typeof [] == "object"
		if(value instanceof Date) { return "date"; } // assume timestamp
		if(value instanceof dojo._Url){ return "url"; }
		return "object";
	}

	function str2obj(/*String*/ value, /*String*/ type){
		// summary
		//	Convert given string value to given type
		switch(type){
			case "string":
				return value;
			case "number":
				return value.length ? Number(value) : null;
			case "boolean":
				return typeof value == "boolean" ? value : !(value.toLowerCase()=="false");
			case "function":
				if(dojo.isFunction(value)){
					return value;
				}
				try{
					if(value.search(/[^\w\.]+/i) != -1){
						// TODO: "this" here won't work
						value = dijit.util.parser._nameAnonFunc(new Function(value), this);
					}
					return dojo.getObject(value, false);
				}catch(e){ return new Function(); }
			case "array":
				return value.split(";");
			case "date":
				return dojo.date.serial.fromRfc3339(value);
			case "url":
//PORT FIXME: is value absolute or relative?  Need to join with "/"?
				return dojo.baseUrl + value;
			default:
				try{ eval("var tmp = "+value); return tmp; }
				catch(e){ return value; }
		}
	}

	var widgetClasses = {
		// map from fully qualified name (like "dijit.Button") to structure like
		// { cls: dijit.Button, params: {caption: "string", disabled: "boolean"} }
	};

	function getWidgetClassInfo(/*String*/ className){
		// className:
		//	fully qualified name (like "dijit.Button")
		// returns:
		//	structure like
		//	{ cls: dijit.Button, params: {caption: "string", disabled: "boolean"} }

		if(!widgetClasses[className]){
			// get pointer to widget class
			var cls = dojo.getObject(className);
			var proto = cls.prototype;

			// get table of parameter names & types
			var params={};
			for(var name in proto){
				if(name.charAt(0)=="_"){ continue; } 	// skip internal properties
				var defVal = proto[name];
				params[name]=val2type(defVal);
			}

			widgetClasses[className] = { cls: cls, params: params };
		}
		return widgetClasses[className];
	}

	this.instantiate = function(nodes){
		// summary:
		//	Takes array of nodes, and turns them into widgets
		//	Calls their layout method to allow them to connect with any children
		var thelist = [];
		dojo.forEach(nodes, function(node){
			if(!node){ return; }
			var type = node.getAttribute('dojoType');
			var clsInfo = getWidgetClassInfo(type);
			var params = {};
			for(var attrName in clsInfo.params){
				var attrValue = node.getAttribute(attrName);
				if(attrValue != null){
					var attrType = clsInfo.params[attrName];
					params[attrName] = str2obj(attrValue, attrType);
				}
			}
			thelist.push(new clsInfo.cls(params, node));
		});

		// first sort the widgets so that we can do a top-down wiring phase
		thelist.sort(function(a,b){
			// prefer containers to leaf node nodes; keep in document order otherwise
			return b.getParent && !a.getParent;
		});

		// now call layout method on each widget so thay can wire up their children
		dojo.forEach(thelist, function(node){
			if(node && node.layout){ node.layout(); }
		});

	};

	this.parse = function(/*DomNode?*/ rootNode){
		// Summary
		//		Search specified node (or root node) recursively for widgets, and instantiate them
		//		Searches for dojoType="qualified.class.name"
		var list = dojo.query('[dojoType]', rootNode);
		this.instantiate(list);
	};
}();

dojo.addOnLoad(function(){ dijit.util.parser.parse(); });

//PORT belongs in dojo core?
dijit.util.parser._anonCtr = 0;
dijit.util.parser._anon = {}; // why is this property required?
dijit.util.parser._nameAnonFunc = function(/*Function*/anonFuncPtr, /*Object*/thisObj, /*Boolean*/searchForNames){
	// summary:
	//		Creates a reference to anonFuncPtr in thisObj with a completely
	//		unique name. The new name is returned as a String.  If
	//		searchForNames is true, an effort will be made to locate an
	//		existing reference to anonFuncPtr in thisObj, and if one is found,
	//		the existing name will be returned instead. The default is for
	//		searchForNames to be false.
	var isIE = dojo.isIE;
	var jpn = "$joinpoint";
	var nso = (thisObj|| dijit.util.parser._anon);
	if(isIE){
		var cn = anonFuncPtr["__dojoNameCache"];
		if(cn && nso[cn] === anonFuncPtr){
			return anonFuncPtr["__dojoNameCache"];
		}else if(cn){
			// hack to see if we've been event-system mangled
			var tindex = cn.indexOf(jpn);
			if(tindex != -1){
				return cn.substring(0, tindex);
			}
		}
	}
	if( (searchForNames) ||
		((dojo.global["djConfig"])&&(djConfig["slowAnonFuncLookups"] == true)) ){
		for(var x in nso){
			if(nso[x] === anonFuncPtr){
				if(isIE){
					anonFuncPtr["__dojoNameCache"] = x;
					// hack to see if we've been event-system mangled
					var tindex = x.indexOf(jpn);
					if(tindex != -1){
						x = x.substring(0, tindex);
					}
				}
				return x;
			}
		}
	}
	var ret = "__"+dijit.util.parser._anonCtr++;
	while(typeof nso[ret] != "undefined"){
		ret = "__"+dijit.util.parser._anonCtr++;
	}
	nso[ret] = anonFuncPtr;
	return ret; // String
}
<commit_msg>Refs #2654: IE does not like boolean return type for compare function return the parsed widgets<commit_after>dojo.provide("dijit.util.parser");

dojo.require("dijit.util.manager");
dojo.require("dojo.date.serial");

dijit.util.parser = new function(){

	function val2type(/*Object*/ value){
		// summary:
		//	Returns name of type of given value.
		//	Like dojo.lang but more types.

		if(dojo.isString(value)){ return "string"; }
		if(typeof value == "number"){ return "number"; }
		if(typeof value == "boolean"){ return "boolean"; }
		if(dojo.isFunction(value)){ return "function"; }
		if(dojo.isArray(value)){ return "array"; } // typeof [] == "object"
		if(value instanceof Date) { return "date"; } // assume timestamp
		if(value instanceof dojo._Url){ return "url"; }
		return "object";
	}

	function str2obj(/*String*/ value, /*String*/ type){
		// summary
		//	Convert given string value to given type
		switch(type){
			case "string":
				return value;
			case "number":
				return value.length ? Number(value) : null;
			case "boolean":
				return typeof value == "boolean" ? value : !(value.toLowerCase()=="false");
			case "function":
				if(dojo.isFunction(value)){
					return value;
				}
				try{
					if(value.search(/[^\w\.]+/i) != -1){
						// TODO: "this" here won't work
						value = dijit.util.parser._nameAnonFunc(new Function(value), this);
					}
					return dojo.getObject(value, false);
				}catch(e){ return new Function(); }
			case "array":
				return value.split(";");
			case "date":
				return dojo.date.serial.fromRfc3339(value);
			case "url":
//PORT FIXME: is value absolute or relative?  Need to join with "/"?
				return dojo.baseUrl + value;
			default:
				try{ eval("var tmp = "+value); return tmp; }
				catch(e){ return value; }
		}
	}

	var widgetClasses = {
		// map from fully qualified name (like "dijit.Button") to structure like
		// { cls: dijit.Button, params: {caption: "string", disabled: "boolean"} }
	};

	function getWidgetClassInfo(/*String*/ className){
		// className:
		//	fully qualified name (like "dijit.Button")
		// returns:
		//	structure like
		//	{ cls: dijit.Button, params: {caption: "string", disabled: "boolean"} }

		if(!widgetClasses[className]){
			// get pointer to widget class
			var cls = dojo.getObject(className);
			var proto = cls.prototype;

			// get table of parameter names & types
			var params={};
			for(var name in proto){
				if(name.charAt(0)=="_"){ continue; } 	// skip internal properties
				var defVal = proto[name];
				params[name]=val2type(defVal);
			}

			widgetClasses[className] = { cls: cls, params: params };
		}
		return widgetClasses[className];
	}

	this.instantiate = function(nodes){
		// summary:
		//	Takes array of nodes, and turns them into widgets
		//	Calls their layout method to allow them to connect with any children
		var thelist = [];
		dojo.forEach(nodes, function(node){
			if(!node){ return; }
			var type = node.getAttribute('dojoType');
			var clsInfo = getWidgetClassInfo(type);
			var params = {};
			for(var attrName in clsInfo.params){
				var attrValue = node.getAttribute(attrName);
				if(attrValue != null){
					var attrType = clsInfo.params[attrName];
					params[attrName] = str2obj(attrValue, attrType);
				}
			}
			thelist.push(new clsInfo.cls(params, node));
		});

		// first sort the widgets so that we can do a top-down wiring phase
		thelist.sort(function(a,b){
			// prefer containers to leaf nodes; keep in document order otherwise
			return (b.getParent && !a.getParent)?1:0;
		});

		// now call layout method on each widget so they can wire up their children
		dojo.forEach(thelist, function(node){
			if(node && node.layout){ node.layout(); }
		});
		return thelist;
	};

	this.parse = function(/*DomNode?*/ rootNode){
		// Summary
		//		Search specified node (or root node) recursively for widgets, and instantiate them
		//		Searches for dojoType="qualified.class.name"
		var list = dojo.query('[dojoType]', rootNode);
		return this.instantiate(list);
	};
}();

dojo.addOnLoad(function(){ dijit.util.parser.parse(); });

//PORT belongs in dojo core?
dijit.util.parser._anonCtr = 0;
dijit.util.parser._anon = {}; // why is this property required?
dijit.util.parser._nameAnonFunc = function(/*Function*/anonFuncPtr, /*Object*/thisObj, /*Boolean*/searchForNames){
	// summary:
	//		Creates a reference to anonFuncPtr in thisObj with a completely
	//		unique name. The new name is returned as a String.  If
	//		searchForNames is true, an effort will be made to locate an
	//		existing reference to anonFuncPtr in thisObj, and if one is found,
	//		the existing name will be returned instead. The default is for
	//		searchForNames to be false.
	var isIE = dojo.isIE;
	var jpn = "$joinpoint";
	var nso = (thisObj|| dijit.util.parser._anon);
	if(isIE){
		var cn = anonFuncPtr["__dojoNameCache"];
		if(cn && nso[cn] === anonFuncPtr){
			return anonFuncPtr["__dojoNameCache"];
		}else if(cn){
			// hack to see if we've been event-system mangled
			var tindex = cn.indexOf(jpn);
			if(tindex != -1){
				return cn.substring(0, tindex);
			}
		}
	}
	if( (searchForNames) ||
		((dojo.global["djConfig"])&&(djConfig["slowAnonFuncLookups"] == true)) ){
		for(var x in nso){
			if(nso[x] === anonFuncPtr){
				if(isIE){
					anonFuncPtr["__dojoNameCache"] = x;
					// hack to see if we've been event-system mangled
					var tindex = x.indexOf(jpn);
					if(tindex != -1){
						x = x.substring(0, tindex);
					}
				}
				return x;
			}
		}
	}
	var ret = "__"+dijit.util.parser._anonCtr++;
	while(typeof nso[ret] != "undefined"){
		ret = "__"+dijit.util.parser._anonCtr++;
	}
	nso[ret] = anonFuncPtr;
	return ret; // String
}
<|endoftext|>


<commit_before>'use strict';

const uuid = require('node-uuid');
let Boom = require('boom');

module.exports = {
    create: create
};

function create(statusCode = 500, message = 'Internal server error', data = {}) {
    let error = Boom.create(statusCode, message, data);

    return {
        statusCode: error.output.payload.statusCode,
        error: error.output.payload.error,
        message: error.output.payload.message,
        timestamp: Date.now(),
        reference: uuid.v4(),
        headers: error.output.headers,
        data: error.data
    };
}
<commit_msg>removed unused file<commit_after><|endoftext|>


<commit_before>var http = require('https');
var request = require('request');
var fs = require('fs');

var parseDiff = require('parse-diff');
var CLIEngine = require("eslint").CLIEngine;
const CHECKED_DIR = require('../constants').CHECKED_DIR;

const GITHUB_TOKEN = process.env.GITHUB_TOKEN || '';

var eslintCli = new CLIEngine({
    fix: false,
    envs: [
        "node",
        "browser",
        "worker",
        "jquery"
    ],
    baseConfig: {
        extends: "aibnb",
    },
    rules: {
        "new-cap": [
            2,
            {
                "capIsNewExceptions": [
                    "FluxMixin",
                    "StoreWatchMixin"
                ]
            }
        ],
        "react/prefer-es6-class": 0,
        "react/no-deprecated": 0,
        "react/no-find-dom-node": 0,
        "global-require": 0,
        "import/no-webpack-loader-syntax": 0,
        "react/jsx-filename-extension": [1, {
            "extensions": [".js", ".jsx"]
        }],
        "import/no-extraneous-dependencies": 0,
        "import/no-unresolved": 0,
        "jsx-a11y/href-no-hash": 0
    },
    "parser": "babel-eslint",
    "parserOptions": {
        "ecmaVersion": 6,
        "ecmaFeatures": {
            "experimentalObjectRestSpread": true
        }
    },
    "globals": [
        "_",
        "tinymce",
        "jsonh",
        "compileSectionData",
        "dataprebuiltId",
        "autoresponderStatus",
        "MagicWand",
        "tinyMCE",
        "FB"
    ]
});

const checkEslint = pathList => {
    return eslintCli.executeOnFiles(pathList);
}

const getFilesFromDiff = diff => parseDiff(diff);

const regExpFilter = regExp => filename => regExp.test(filename);

const getFilePath = (repositoryOwner, repositoryName, sha, filename) =>
    `/${repositoryOwner}/${repositoryName}/${sha}/${filename}`;

const getGitHubHeaders = () => Object(
    {
        Authorization: `token ${GITHUB_TOKEN}`,
        Accept: 'application/vnd.github.v3.raw',
        'User-Agent': 'mrlinter',
        'content-type': 'application/json',
    }
)

const getRawGitHubOptions = opts => Object(
    {
        protocol: 'https:',
        host: 'raw.githubusercontent.com',
        path: getFilePath(opts.owner, opts.repository, opts.sha, opts.filename),
        headers: getGitHubHeaders(),
    }
);

const getGitHubFilePromise = (url, mediaType = 'application/vnd.github.v3.raw') => new Promise((resolve, reject) => {
    const githubRequestOptions = {
        url: url,
        headers: getGitHubHeaders(),
    };
    githubRequestOptions.headers['Accept'] = mediaType;
    request(githubRequestOptions, (error, response, body) => {
        const statusCode = response.statusCode;
        if (statusCode === 200) {
            resolve(body);
        } else {
            if (statusCode === 301 && response.headers.location) {
                resolve(getGitHubFilePromise(response.headers.location));
            } else {
                reject(statusCode);
            }
        }
    });
});

const prepareComment = (report, author, filePath) => {
    const commentHeader = `Hello @${author}! Thanks for submitting the PR.\n\n`;
    // const commentHeader = `Hello ${author}! Thanks for updating the PR.\n\n`;
    let commentBody = '';
    if (report.errorCount) {
        console.log(`Report have the ${report.errorCount} errors in ${report.results.length} files`);
        report.results.forEach((result, resultIndex) => {
            const resultFilename = filePath[result.filePath.split('/').slice(-1)];
            console.log(`Start processing ${resultIndex + 1} result of ${report.results.length} for ${resultFilename}`);
            let resultCommentPart = result.errorCount
                ? `- In the file [**${resultFilename}**], following are the ESLint issues :\n`
                : `- There are no ESLint issues in the file [**${resultFilename}**]\n`;
            result.messages.forEach((message, messageIndex) => {
                console.log(`Start processing ${messageIndex + 1} of ${result.messages.length} message of ${resultFilename}`)
                resultCommentPart += `> ${message.line}:${message.column}\t${message.message}\t${message.ruleId}\n`
            });
            commentBody += `${resultCommentPart}\n\n`
        })
    }
    return {
        header: commentHeader,
        body: commentBody,
    }
}

const getCheckedDirName = requestId => `${CHECKED_DIR}-${requestId}`;

module.exports = {
    getGitHubFilePromise: getGitHubFilePromise,
    getFilesFromDiff: getFilesFromDiff,
    regExpFilter: regExpFilter,
    getFilePath: getFilePath,
    getGitHubHeaders: getGitHubHeaders,
    getRawGitHubOptions: getRawGitHubOptions,
    checkEslint: checkEslint,
    prepareComment: prepareComment,
    getCheckedDirName: getCheckedDirName,
}
<commit_msg>airbnb style guide implement<commit_after>var http = require('https');
var request = require('request');
var fs = require('fs');

var parseDiff = require('parse-diff');
var CLIEngine = require("eslint").CLIEngine;
const CHECKED_DIR = require('../constants').CHECKED_DIR;

const GITHUB_TOKEN = process.env.GITHUB_TOKEN || '';

var eslintCli = new CLIEngine({
    fix: false,
    envs: [
        "node",
        "browser",
        "worker",
        "jquery"
    ],
    baseConfig: {
        extends: "airbnb",
    },
    rules: {
        "new-cap": [
            2,
            {
                "capIsNewExceptions": [
                    "FluxMixin",
                    "StoreWatchMixin"
                ]
            }
        ],
        "react/prefer-es6-class": 0,
        "react/no-deprecated": 0,
        "react/no-find-dom-node": 0,
        "global-require": 0,
        "import/no-webpack-loader-syntax": 0,
        "react/jsx-filename-extension": [1, {
            "extensions": [".js", ".jsx"]
        }],
        "import/no-extraneous-dependencies": 0,
        "import/no-unresolved": 0,
        "jsx-a11y/href-no-hash": 0
    },
    "parser": "babel-eslint",
    "parserOptions": {
        "ecmaVersion": 6,
        "ecmaFeatures": {
            "experimentalObjectRestSpread": true
        }
    },
    "globals": [
        "_",
        "tinymce",
        "jsonh",
        "compileSectionData",
        "dataprebuiltId",
        "autoresponderStatus",
        "MagicWand",
        "tinyMCE",
        "FB"
    ]
});

const checkEslint = pathList => {
    return eslintCli.executeOnFiles(pathList);
}

const getFilesFromDiff = diff => parseDiff(diff);

const regExpFilter = regExp => filename => regExp.test(filename);

const getFilePath = (repositoryOwner, repositoryName, sha, filename) =>
    `/${repositoryOwner}/${repositoryName}/${sha}/${filename}`;

const getGitHubHeaders = () => Object(
    {
        Authorization: `token ${GITHUB_TOKEN}`,
        Accept: 'application/vnd.github.v3.raw',
        'User-Agent': 'mrlinter',
        'content-type': 'application/json',
    }
)

const getRawGitHubOptions = opts => Object(
    {
        protocol: 'https:',
        host: 'raw.githubusercontent.com',
        path: getFilePath(opts.owner, opts.repository, opts.sha, opts.filename),
        headers: getGitHubHeaders(),
    }
);

const getGitHubFilePromise = (url, mediaType = 'application/vnd.github.v3.raw') => new Promise((resolve, reject) => {
    const githubRequestOptions = {
        url: url,
        headers: getGitHubHeaders(),
    };
    githubRequestOptions.headers['Accept'] = mediaType;
    request(githubRequestOptions, (error, response, body) => {
        const statusCode = response.statusCode;
        if (statusCode === 200) {
            resolve(body);
        } else {
            if (statusCode === 301 && response.headers.location) {
                resolve(getGitHubFilePromise(response.headers.location));
            } else {
                reject(statusCode);
            }
        }
    });
});

const prepareComment = (report, author, filePath) => {
    const commentHeader = `Hello @${author}! Thanks for submitting the PR.\n\n`;
    // const commentHeader = `Hello ${author}! Thanks for updating the PR.\n\n`;
    let commentBody = '';
    if (report.errorCount) {
        console.log(`Report have the ${report.errorCount} errors in ${report.results.length} files`);
        report.results.forEach((result, resultIndex) => {
            const resultFilename = filePath[result.filePath.split('/').slice(-1)];
            console.log(`Start processing ${resultIndex + 1} result of ${report.results.length} for ${resultFilename}`);
            let resultCommentPart = result.errorCount
                ? `- In the file [**${resultFilename}**], following are the ESLint issues :\n`
                : `- There are no ESLint issues in the file [**${resultFilename}**]\n`;
            result.messages.forEach((message, messageIndex) => {
                console.log(`Start processing ${messageIndex + 1} of ${result.messages.length} message of ${resultFilename}`)
                resultCommentPart += `> ${message.line}:${message.column}\t${message.message}\t${message.ruleId}\n`
            });
            commentBody += `${resultCommentPart}\n\n`
        })
    }
    return {
        header: commentHeader,
        body: commentBody,
    }
}

const getCheckedDirName = requestId => `${CHECKED_DIR}-${requestId}`;

module.exports = {
    getGitHubFilePromise: getGitHubFilePromise,
    getFilesFromDiff: getFilesFromDiff,
    regExpFilter: regExpFilter,
    getFilePath: getFilePath,
    getGitHubHeaders: getGitHubHeaders,
    getRawGitHubOptions: getRawGitHubOptions,
    checkEslint: checkEslint,
    prepareComment: prepareComment,
    getCheckedDirName: getCheckedDirName,
}
<|endoftext|>


<commit_before>import * as symbols from '../../src/symbols.js';
import KeyboardDirectionMixin from '../../src/KeyboardDirectionMixin.js';

class KeyboardDirectionMixinTest extends KeyboardDirectionMixin(HTMLElement) {
  [symbols.goRight]() {
    if (super[symbols.goRight]) { super[symbols.goRight](); }
    return true;
  }
}
customElements.define('keyboard-direction-test', KeyboardDirectionMixinTest);

describe("KeyboardDirectionMixin", () => {

  it("maps a Right arrow key to a goRight action", () => {
    const fixture = new KeyboardDirectionMixinTest();
    const spy = sinon.spy(fixture, symbols.goRight);
    const result = fixture[symbols.keydown]({
      key: 'ArrowRight'
    });
    assert(spy.calledOnce);
    assert(result);
  });

  it("ignores a Right arrow key when orientation is vertical", () => {
    const fixture = new KeyboardDirectionMixinTest();
    fixture.state = {
      orientation: 'vertical'
    };
    const spy = sinon.spy(fixture, symbols.goRight);
    const result = fixture[symbols.keydown]({
      key: 'ArrowRight'
    });
    assert(!spy.calledOnce);
    assert(!result);
  });

  it("ignores a Right arrow key if the meta (command) key was pressed", () => {
    const fixture = new KeyboardDirectionMixinTest();
    const spy = sinon.spy(fixture, symbols.goRight);
    const result = fixture[symbols.keydown]({
      altKey: true,
      key: 'ArrowRight'
    });
    assert(!spy.calledOnce);
    assert(!result);
  });

});
<commit_msg>Fix broken unit test which resulted from deprecating KeyboardDirectionMixin defining a public orientation property.<commit_after>import * as symbols from '../../src/symbols.js';
import KeyboardDirectionMixin from '../../src/KeyboardDirectionMixin.js';

class KeyboardDirectionMixinTest extends KeyboardDirectionMixin(HTMLElement) {

  constructor() {
    super();
    this.state = {};
  }

  [symbols.goRight]() {
    if (super[symbols.goRight]) { super[symbols.goRight](); }
    return true;
  }

}
customElements.define('keyboard-direction-test', KeyboardDirectionMixinTest);

describe("KeyboardDirectionMixin", () => {

  it("maps a Right arrow key to a goRight action", () => {
    const fixture = new KeyboardDirectionMixinTest();
    const spy = sinon.spy(fixture, symbols.goRight);
    const result = fixture[symbols.keydown]({
      key: 'ArrowRight'
    });
    assert(spy.calledOnce);
    assert(result);
  });

  it("ignores a Right arrow key when orientation is vertical", () => {
    const fixture = new KeyboardDirectionMixinTest();
    Object.assign(fixture.state, {
      orientation: 'vertical'
    });
    const spy = sinon.spy(fixture, symbols.goRight);
    const result = fixture[symbols.keydown]({
      key: 'ArrowRight'
    });
    assert(!spy.calledOnce);
    assert(!result);
  });

  it("ignores a Right arrow key if the meta (command) key was pressed", () => {
    const fixture = new KeyboardDirectionMixinTest();
    const spy = sinon.spy(fixture, symbols.goRight);
    const result = fixture[symbols.keydown]({
      altKey: true,
      key: 'ArrowRight'
    });
    assert(!spy.calledOnce);
    assert(!result);
  });

});
<|endoftext|>


<commit_before>import React from 'react';
import {
  findRenderedDOMComponentWithClass,
  Simulate,
  renderIntoDocument
} from 'react-addons-test-utils';
import chai, { expect } from 'chai';
import spies from 'chai-spies';

import ProfilePreapproved from '../../../frontend/src/components/ProfilePreapproved';

var Wrapper = React.createClass({
    render() {
      return (
{this.props.children}
);
    }
});

const createElement = (props, className='ProfilePreapproved') => {
  // For shallow components
  const rendered = renderIntoDocument(<Wrapper><ProfilePreapproved {...props} /></Wrapper>);
  return findRenderedDOMComponentWithClass(rendered, className);
};

chai.use(spies);

describe('ProfilePreapproved component', () => {
  it('should show the preapproved amount and the difference', () => {
    const element = createElement({
      userid: 1,
      preapprovalDetails: {
        maxTotalAmountOfAllPayments: '2000.00',
        curPaymentsAmount: '100.00',
      },
      getPreapprovalKey: () => {}
    }, 'ProfilePreapproved-balance');

    expect(element.innerHTML).to.contain('$1,900.00');
    expect(element.innerHTML).to.contain('$2,000.00');
  });

  it('should repreapproved the account', () => {
    const getPreapprovalKey = chai.spy(() => {});
    const userid = 1;

    const element = createElement({
      userid,
      preapprovalDetails: {
        maxTotalAmountOfAllPayments: '2000.00',
        curPaymentsAmount: '100.00',
      },
      getPreapprovalKey
    }, 'ProfilePreapproved-reapprove');

    Simulate.click(element);
    expect(getPreapprovalKey).to.have.been.called.with(userid);
  });
});
<commit_msg>updated test for new copy<commit_after>import React from 'react';
import {
  findRenderedDOMComponentWithClass,
  Simulate,
  renderIntoDocument
} from 'react-addons-test-utils';
import chai, { expect } from 'chai';
import spies from 'chai-spies';

import ProfilePreapproved from '../../../frontend/src/components/ProfilePreapproved';

var Wrapper = React.createClass({
    render() {
      return (
{this.props.children}
);
    }
});

const createElement = (props, className='ProfilePreapproved') => {
  // For shallow components
  const rendered = renderIntoDocument(<Wrapper><ProfilePreapproved {...props} /></Wrapper>);
  return findRenderedDOMComponentWithClass(rendered, className);
};

chai.use(spies);

describe('ProfilePreapproved component', () => {
  it('should show the preapproved amount remaining', () => {
    const element = createElement({
      userid: 1,
      preapprovalDetails: {
        maxTotalAmountOfAllPayments: '2000.00',
        curPaymentsAmount: '100.00',
      },
      getPreapprovalKey: () => {}
    }, 'ProfilePreapproved-balance');

    expect(element.innerHTML).to.contain('$1,900.00');
  });

  it('should repreapproved the account', () => {
    const getPreapprovalKey = chai.spy(() => {});
    const userid = 1;

    const element = createElement({
      userid,
      preapprovalDetails: {
        maxTotalAmountOfAllPayments: '2000.00',
        curPaymentsAmount: '100.00',
      },
      getPreapprovalKey
    }, 'ProfilePreapproved-reapprove');

    Simulate.click(element);
    expect(getPreapprovalKey).to.have.been.called.with(userid);
  });
});
<|endoftext|>


<commit_before>'use strict';
import * as fs from 'fs';
import * as actions from '../common/actions.json';
import * as keymapping from '../common/keymapping.json';

export default class Utils {

    constructor() { }

    get Actions() {
        return actions;
    }

    get KeyMapping() {
        return keymapping;
    }

    // Get ide name and userKeys json files, and returns an array of ActionName:{actionId:***, shortcut:****}, the shortcut as string
	getNormalizedListByIDE(ideName, userKeys) {
		var arr = [];
		for (action in userActionsJson) {
			var obj = {};
			obj.actionId = getActionIdByIde(action, ideName);
			obj.shortcut = keyArrayToString(userkeys[action].shortCut)
			arr[action] = obj;
		}

		return arr;
	}
	// Get keyarray and ide name and return string represent the keystroke in the ide shortcuts file.
	keyArrayToString(keyArray, ideName) {
		var returnVal = " ";
		for (key in keyMap) {
			returnVal += getKeyBy
			Ide(key, ideName);
			returnVal += getKeyByIde("DELIMETER", ideName);
		}

		// Return last char
		returnVal = returnVal.substring(0, returnVal.length  - 1);

		return returnVal;
	}

	getActionIdByIde(actionName, ide) {
		return actions[actionName]["IDE"][ide];
	}

	getKeyByIde(key,ideName) {
		return keymapping[key]["IDE"][ideName];
	}
};
<commit_msg>change normalize list format<commit_after>'use strict';
import * as fs from 'fs';
import * as actions from '../common/actions.json';
import * as keymapping from '../common/keymapping.json';

export default class Utils {

    constructor() { }

    get Actions() {
        return actions;
    }

    get KeyMapping() {
        return keymapping;
    }

    // Get ide name and userKeys json files, and returns an array of ActionName:{actionId:***, shortcut:****}, the shortcut as string
	getNormalizedListByIDE(ideName, userKeys) {
		var arr = [];
		for (action of userActionsJson) {
			var obj = {};
			obj.action = getActionIdByIde(action.action, ideName);
			obj.keys = keyArrayToString(userkeys[action].keys)
			arr.append(obj);
		}

		return arr;
	}
	// Get keyarray and ide name and return string represent the keystroke in the ide shortcuts file.
	keyArrayToString(keyArray, ideName) {
		var returnVal = " ";
		for (key in keyMap) {
			returnVal += getKeyBy
			getKeyByIIde(key, ideName);
			returnVal += getKeyByIde("DELIMETER", ideName);
		}

		// Return last char
		returnVal = returnVal.substring(0, returnVal.length  - 1);

		return returnVal;
	}

	getActionIdByIde(actionName, ide) {
		return actions[actionName]["IDE"][ide];
	}

	getKeyByIde(key,ideName) {
		return keymapping[key]["IDE"][ideName];
	}
};
<|endoftext|>


<commit_before>/**
 *
 * This test is needing all three files to be present
 *  - testSendData.js      : the main entry point to the test case
 *  - SendDataConnector.js : logic that handles the connection & data sending parts
 *  - SendDataTCPServer.js : logic that handles the server endpoint for connections & data receiving/replying for the test
 *
 * In this test case we try connecting to the remote peer and send N-bytes of data (where N should be big amount)
 * If the sending fails in midway, the logic will do reconnection to the same peer and send any remaining bytes until the whole N-bytes are sent over
 * We measure the time it takes to send the data and report that back.
 *
 * If specified the sending is done multiple times for each peer.
 *
 * Note that we don't want to sent the data both ways, and for this reason the server is not simply echoing back the data sent,
 * but actually only sends verifications on getting some predefined amount of data, currently the amount is specified as 10000 bytes
 */

'use strict';

var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;

var ThaliEmitter = require('thali/thaliemitter');

var SendDataTCPServer = require('./SendDataTCPServer');
var SendDataConnector = require('./SendDataConnector');

/*
"data": {
    "timeout"        : Specifies the timeout when we would end test (in case we have not already finished all connection rounds yet)
    "rounds"         : Specifies how many connections to each peer we should be doing
    "dataAmount"     : Specifies the amount of data we need ro send over each connection made
    "dataTimeout"    : Specifies timeout used for sending the data and waiting for the reply before we do retry for the connection round.
    "conReTryTimeout": Specifies the time value we wait after unsuccessful connection attempt, before we try again.
    "conReTryCount"  : Specifies the times we do retries for unsuccessful connection attempts before we mark the test round failed
    }
*/

function testSendData(jsonData, name, addressList) {

  var self = this;

  console.log(
    'testSendData created ' + JSON.stringify(jsonData) +
    "bt-address length : " + addressList.length
  );

  this.name = name;
  this.commandData = jsonData;
  this.emitter = new ThaliEmitter();
  this.toFindCount = jsonData.peerCount;
  this.BluetoothAddressList = addressList.length > 0 ? addressList : null;

  this.startTime = new Date();
  this.endTime = new Date();
  this.endReason = "";

  this.debugCallback = function (data) {
    self.emit('debug', data);
  }

  this.doneCallback = function (data) {
    console.log('---- round done--------');
    var resultData = JSON.parse(data);

    var peerAddress  = 0;
    var peerTryCount = 0;
    var areAllTestOk = true;

    // if we use the address list, then we try getting all connections to be successful
    // thus we re-try the ones that were not successful
    // and we schedule the re-try to be handled after all other peers we have in the list currently
    if (self.BluetoothAddressList.length > 0) {
      for (var i = 0; i < resultData.length; i++) {
        if (resultData[i].result != "OK") {
          areAllTestOk = false;
          peerAddress = resultData[i].name;
          peerTryCount = resultData[i].tryCount;
        }
      }
    }

    // if all was ok, then we'll store the data values, otherwise we'll put the peer back to the
    // address list
    if (areAllTestOk) {
      for (var i = 0; i < resultData.length; i++) {
        self.resultArray.push(resultData[i]);
      }
    } else if (peerAddress != 0) { //we gotta re-try it later
      console.log('---- gotta redo : ' + peerAddress + ", try count now: " + peerTryCount);
      self.BluetoothAddressList.push({"address":peerAddress,"tryCount":peerTryCount});
    }

    self.testStarted = false;
    if (!self.doneAlready) {
      self.startWithNextDevice();
    }
  }

  this.foundSofar = 0;
  this.timerId = null;
  this.foundPeers = {};
  this.resultArray = [];

  this.peerAvailabilityChanged = function(peers) {

    // We have address list, so we use it instead
    if (self.BluetoothAddressList && self.BluetoothAddressList.length > 0) {
      return;
    }

    console.log('peerAvailabilityChanged ' + JSON.stringify(peers));

    for (var i = 0; i < peers.length; i++) {

      var peer = peers[i];

      if ((!self.foundPeers[peer.peerIdentifier]) ||
          (!self.foundPeers[peer.peerIdentifier].doneAlready)) {

        self.foundPeers[peer.peerIdentifier] = peer;
        console.log("Found peer : " + peer.peerName + ", Available: " + peer.peerAvailable);
      }
    }

    if (!self.testStarted) {
        self.startWithNextDevice();
    }
  }
}

inherits(testSendData, EventEmitter);

testSendData.prototype.start = function(serverPort) {

  var self = this;
  this.doneAlready = false;
  this.testServer = new SendDataTCPServer(serverPort);
  this.testConnector = new SendDataConnector(
    this.commandData.rounds,
    this.commandData.dataAmount,
    this.commandData.conReTryTimeout,
    this.commandData.conReTryCount,
    this.commandData.dataTimeout
  );

  this.testConnector.on('done', this.doneCallback);
  this.testConnector.on('debug',this.debugCallback);

  console.log('check server');
  var serverPort = this.testServer.getServerPort();
  console.log('serverPort is ' + serverPort);

  this.emitter.on(ThaliEmitter.events.PEER_AVAILABILITY_CHANGED, this.peerAvailabilityChanged);
  this.emitter.startBroadcasting(self.name, serverPort, function (err) {
    if (err) {
      console.log('StartBroadcasting returned error ' + err);
    } else {
      console.log('StartBroadcasting started ok');
      console.log(self.BluetoothAddressList);

      if (self.BluetoothAddressList && self.BluetoothAddressList.length > 0) {
        if (!self.testStarted) {
          self.startWithNextDevice();
        }
      }
    }
  });

  if (this.commandData.timeout) {
    this.timerId = setTimeout(function() {
      console.log('timeout now');
      if (!self.doneAlready) {
        self.endReason = "TIMEOUT";
        self.emit('debug', "*** TIMEOUT ***");
        self.weAreDoneNow();
      }
    }, this.commandData.timeout);
  }
}

testSendData.prototype.stop = function(doReport) {

  var self = this;

  console.log('testSendData stopped');

  this.emitter.removeListener(
    ThaliEmitter.events.PEER_AVAILABILITY_CHANGED, this.peerAvailabilityChanged
  );

  this.emitter.stopBroadcasting(function (err) {
    if (err) {
      console.log('StopBroadcasting returned error ' + err);
    } else {
      console.log('StopBroadcasting went ok');
    }
  });

  if (this.timerId != null) {
    clearTimeout(this.timerId);
    this.timerId = null;
  }

  if (doReport){
    this.emit('debug', "---- sendReportNow");
    this.sendReportNow();
  }

  if (this.testConnector != null) {
    this.testConnector.Stop(function () {
      self.testConnector.removeListener('done', self.doneCallback);
      self.testConnector.removeListener('debug', self.debugCallback);
      self.testConnector = null;
    });
  }

  this.testServer.stopServer(function () {
    // No need to do anything since this is the end of this test
  });
}

testSendData.prototype.startWithNextDevice = function() {

  console.log("startWithNextDevice");

  if (this.doneAlready || this.testConnector == null) {
    return;
  }

  if (this.BluetoothAddressList) {

    if (this.BluetoothAddressList.length == 0) {
      this.endReason = "OK";
      this.weAreDoneNow();
      return;
    }

    console.log('do fake peer & start');

    var fakePeer = {};
    fakePeer.peerAvailable = true;

    var addressItem = this.BluetoothAddressList.shift();
    fakePeer.peerName = addressItem.address;
    fakePeer.peerIdentifier = addressItem.address;
    fakePeer.tryCount = (addressItem.tryCount + 1);

    console.log('Connect to fake peer: ' + fakePeer.peerIdentifier);
    this.testConnector.Start(fakePeer);
    return;

  } else {

    if (this.foundSofar >= this.toFindCount) {
      this.endReason = "OK";
      this.weAreDoneNow();
      return;
    }

    for (var peerId in this.foundPeers) {
      if (this.foundPeers[peerId].peerAvailable && !this.foundPeers[peerId].doneAlready) {
        this.testStarted = true;
        this.emit('debug', '--- start for : ' + this.foundPeers[peerId].peerName + ' ---');
        this.foundSofar++
        console.log('device[' + this.foundSofar + ']: ' + this.foundPeers[peerId].peerIdentifier);

        this.foundPeers[peerId].doneAlready = true;
        this.testConnector.Start(this.foundPeers[peerId]);
        return;
      }
    }
  }
}

testSendData.prototype.weAreDoneNow = function() {
  var self = this;

  if (this.doneAlready || this.testConnector == null) {
    return;
  }

  if (this.timerId != null) {
    clearTimeout(this.timerId);
    this.timerId = null;
  }

  console.log('weAreDoneNow, resultArray.length: ' + this.resultArray.length);
  this.doneAlready = true;
  this.sendReportNow();

  if (this.testConnector != null){
    this.testConnector.Stop(function () {
      self.testConnector.removeListener('done', self.doneCallback);
      self.testConnector.removeListener('debug', self.debugCallback);
      self.testConnector = null;
    });
  }

  // The test server can't be stopped here, because even though this device
  // is done with it's own list of peers, it might be still acting as a test
  // peer for some other devices and thus the server is might still be needed.
}

testSendData.prototype.sendReportNow = function() {

  this.endTime = new Date();

  console.log("sendReportNow");

  if (this.testConnector != null) {
    var isAlreadyAdded = false;
    var currentTest = this.testConnector.getCurrentTest();

    //then get any data that has not been reported yet. i.e. the full rounds have not been done yet
    var resultData = this.testConnector.getResultArray();
    for (var i = 0; i < resultData.length; i++) {
      this.resultArray.push(resultData[i]);

      if (currentTest && currentTest.name == resultData[i].name) {
        isAlreadyAdded = true;
      }
    }

    if (!isAlreadyAdded && currentTest) {
      this.resultArray.push(currentTest);
    }
  }

  if (this.BluetoothAddressList) {
    for (var ii = 0; ii < this.BluetoothAddressList.length; ii++) {
      if (this.BluetoothAddressList[ii]){
        this.resultArray.push( {
          "connections": this.BluetoothAddressList[ii].tryCount,
          "name": this.BluetoothAddressList[ii].address,
          "time": 0,
          "result": "Fail"
        });
      }
    }
  }

  this.emit('debug', "---- finished : send-data -- ");
  var responseTime = this.endTime - this.startTime;

  this.emit('done', JSON.stringify({
    "name:": this.name,
    "time": responseTime,
    "result": this.endReason,
    "sendList": this.resultArray
  }));
}

module.exports = testSendData;
<commit_msg>Check existence of bt address list<commit_after>/**
 *
 * This test is needing all three files to be present
 *  - testSendData.js      : the main entry point to the test case
 *  - SendDataConnector.js : logic that handles the connection & data sending parts
 *  - SendDataTCPServer.js : logic that handles the server endpoint for connections & data receiving/replying for the test
 *
 * In this test case we try connecting to the remote peer and send N-bytes of data (where N should be big amount)
 * If the sending fails in midway, the logic will do reconnection to the same peer and send any remaining bytes until the whole N-bytes are sent over
 * We measure the time it takes to send the data and report that back.
 *
 * If specified the sending is done multiple times for each peer.
 *
 * Note that we don't want to sent the data both ways, and for this reason the server is not simply echoing back the data sent,
 * but actually only sends verifications on getting some predefined amount of data, currently the amount is specified as 10000 bytes
 */

'use strict';

var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;

var ThaliEmitter = require('thali/thaliemitter');

var SendDataTCPServer = require('./SendDataTCPServer');
var SendDataConnector = require('./SendDataConnector');

/*
"data": {
    "timeout"        : Specifies the timeout when we would end test (in case we have not already finished all connection rounds yet)
    "rounds"         : Specifies how many connections to each peer we should be doing
    "dataAmount"     : Specifies the amount of data we need ro send over each connection made
    "dataTimeout"    : Specifies timeout used for sending the data and waiting for the reply before we do retry for the connection round.
    "conReTryTimeout": Specifies the time value we wait after unsuccessful connection attempt, before we try again.
    "conReTryCount"  : Specifies the times we do retries for unsuccessful connection attempts before we mark the test round failed
    }
*/

function testSendData(jsonData, name, addressList) {

  var self = this;

  console.log(
    'testSendData created ' + JSON.stringify(jsonData) +
    "bt-address length : " + addressList.length
  );

  this.name = name;
  this.commandData = jsonData;
  this.emitter = new ThaliEmitter();
  this.toFindCount = jsonData.peerCount;
  this.BluetoothAddressList = addressList.length > 0 ? addressList : null;

  this.startTime = new Date();
  this.endTime = new Date();
  this.endReason = "";

  this.debugCallback = function (data) {
    self.emit('debug', data);
  }

  this.doneCallback = function (data) {

    console.log('---- round done--------');

    var resultData = JSON.parse(data);

    var peerAddress  = 0;
    var peerTryCount = 0;
    var areAllTestOk = true;

    // if we use the address list, then we try getting all connections to be successful
    // thus we re-try the ones that were not successful
    // and we schedule the re-try to be handled after all other peers we have in the list currently
    if (self.BluetoothAddressList && self.BluetoothAddressList.length > 0) {
      for (var i = 0; i < resultData.length; i++) {
        if (resultData[i].result != "OK") {
          areAllTestOk = false;
          peerAddress = resultData[i].name;
          peerTryCount = resultData[i].tryCount;
        }
      }
    }

    // if all was ok, then we'll store the data values, otherwise we'll put the peer back to the
    // address list
    if (areAllTestOk) {
      for (var i = 0; i < resultData.length; i++) {
        self.resultArray.push(resultData[i]);
      }
    } else if (peerAddress != 0) { //we gotta re-try it later
      console.log('---- gotta redo : ' + peerAddress + ", try count now: " + peerTryCount);
      self.BluetoothAddressList.push({"address":peerAddress,"tryCount":peerTryCount});
    }

    self.testStarted = false;
    if (!self.doneAlready) {
      self.startWithNextDevice();
    }
  }

  this.foundSofar = 0;
  this.timerId = null;
  this.foundPeers = {};
  this.resultArray = [];

  this.peerAvailabilityChanged = function(peers) {

    // We have address list, so we use it instead
    if (self.BluetoothAddressList && self.BluetoothAddressList.length > 0) {
      return;
    }

    console.log('peerAvailabilityChanged ' + JSON.stringify(peers));

    for (var i = 0; i < peers.length; i++) {

      var peer = peers[i];

      if ((!self.foundPeers[peer.peerIdentifier]) ||
          (!self.foundPeers[peer.peerIdentifier].doneAlready)) {

        self.foundPeers[peer.peerIdentifier] = peer;
        console.log("Found peer : " + peer.peerName + ", Available: " + peer.peerAvailable);
      }
    }

    if (!self.testStarted) {
        self.startWithNextDevice();
    }
  }
}

inherits(testSendData, EventEmitter);

testSendData.prototype.start = function(serverPort) {

  var self = this;
  this.doneAlready = false;
  this.testServer = new SendDataTCPServer(serverPort);
  this.testConnector = new SendDataConnector(
    this.commandData.rounds,
    this.commandData.dataAmount,
    this.commandData.conReTryTimeout,
    this.commandData.conReTryCount,
    this.commandData.dataTimeout
  );

  this.testConnector.on('done', this.doneCallback);
  this.testConnector.on('debug',this.debugCallback);

  console.log('check server');
  var serverPort = this.testServer.getServerPort();
  console.log('serverPort is ' + serverPort);

  this.emitter.on(ThaliEmitter.events.PEER_AVAILABILITY_CHANGED, this.peerAvailabilityChanged);
  this.emitter.startBroadcasting(self.name, serverPort, function (err) {
    if (err) {
      console.log('StartBroadcasting returned error ' + err);
    } else {
      console.log('StartBroadcasting started ok');
      console.log(self.BluetoothAddressList);

      if (self.BluetoothAddressList && self.BluetoothAddressList.length > 0) {
        if (!self.testStarted) {
          self.startWithNextDevice();
        }
      }
    }
  });

  if (this.commandData.timeout) {
    this.timerId = setTimeout(function() {
      console.log('timeout now');
      if (!self.doneAlready) {
        self.endReason = "TIMEOUT";
        self.emit('debug', "*** TIMEOUT ***");
        self.weAreDoneNow();
      }
    }, this.commandData.timeout);
  }
}

testSendData.prototype.stop = function(doReport) {

  var self = this;

  console.log('testSendData stopped');

  this.emitter.removeListener(
    ThaliEmitter.events.PEER_AVAILABILITY_CHANGED, this.peerAvailabilityChanged
  );

  this.emitter.stopBroadcasting(function (err) {
    if (err) {
      console.log('StopBroadcasting returned error ' + err);
    } else {
      console.log('StopBroadcasting went ok');
    }
  });

  if (this.timerId != null) {
    clearTimeout(this.timerId);
    this.timerId = null;
  }

  if (doReport){
    this.emit('debug', "---- sendReportNow");
    this.sendReportNow();
  }

  if (this.testConnector != null) {
    this.testConnector.Stop(function () {
      self.testConnector.removeListener('done', self.doneCallback);
      self.testConnector.removeListener('debug', self.debugCallback);
      self.testConnector = null;
    });
  }

  this.testServer.stopServer(function () {
    // No need to do anything since this is the end of this test
  });
}

testSendData.prototype.startWithNextDevice = function() {

  console.log("startWithNextDevice");

  if (this.doneAlready || this.testConnector == null) {
    return;
  }

  if (this.BluetoothAddressList) {

    if (this.BluetoothAddressList.length == 0) {
      this.endReason = "OK";
      this.weAreDoneNow();
      return;
    }

    console.log('do fake peer & start');

    var fakePeer = {};
    fakePeer.peerAvailable = true;

    var addressItem = this.BluetoothAddressList.shift();
    fakePeer.peerName = addressItem.address;
    fakePeer.peerIdentifier = addressItem.address;
    fakePeer.tryCount = (addressItem.tryCount + 1);

    console.log('Connect to fake peer: ' + fakePeer.peerIdentifier);
    this.testConnector.Start(fakePeer);
    return;

  } else {

    if (this.foundSofar >= this.toFindCount) {
      this.endReason = "OK";
      this.weAreDoneNow();
      return;
    }

    for (var peerId in this.foundPeers) {
      if (this.foundPeers[peerId].peerAvailable && !this.foundPeers[peerId].doneAlready) {
        this.testStarted = true;
        this.emit('debug', '--- start for : ' + this.foundPeers[peerId].peerName + ' ---');
        this.foundSofar++
        console.log('device[' + this.foundSofar + ']: ' + this.foundPeers[peerId].peerIdentifier);

        this.foundPeers[peerId].doneAlready = true;
        this.testConnector.Start(this.foundPeers[peerId]);
        return;
      }
    }
  }
}

testSendData.prototype.weAreDoneNow = function() {
  var self = this;

  if (this.doneAlready || this.testConnector == null) {
    return;
  }

  if (this.timerId != null) {
    clearTimeout(this.timerId);
    this.timerId = null;
  }

  console.log('weAreDoneNow, resultArray.length: ' + this.resultArray.length);
  this.doneAlready = true;
  this.sendReportNow();

  if (this.testConnector != null){
    this.testConnector.Stop(function () {
      self.testConnector.removeListener('done', self.doneCallback);
      self.testConnector.removeListener('debug', self.debugCallback);
      self.testConnector = null;
    });
  }

  // The test server can't be stopped here, because even though this device
  // is done with it's own list of peers, it might be still acting as a test
  // peer for some other devices and thus the server is might still be needed.
}

testSendData.prototype.sendReportNow = function() {

  this.endTime = new Date();

  console.log("sendReportNow");

  if (this.testConnector != null) {
    var isAlreadyAdded = false;
    var currentTest = this.testConnector.getCurrentTest();

    //then get any data that has not been reported yet. i.e. the full rounds have not been done yet
    var resultData = this.testConnector.getResultArray();
    for (var i = 0; i < resultData.length; i++) {
      this.resultArray.push(resultData[i]);

      if (currentTest && currentTest.name == resultData[i].name) {
        isAlreadyAdded = true;
      }
    }

    if (!isAlreadyAdded && currentTest) {
      this.resultArray.push(currentTest);
    }
  }

  if (this.BluetoothAddressList) {
    for (var ii = 0; ii < this.BluetoothAddressList.length; ii++) {
      if (this.BluetoothAddressList[ii]){
        this.resultArray.push( {
          "connections": this.BluetoothAddressList[ii].tryCount,
          "name": this.BluetoothAddressList[ii].address,
          "time": 0,
          "result": "Fail"
        });
      }
    }
  }

  this.emit('debug', "---- finished : send-data -- ");
  var responseTime = this.endTime - this.startTime;

  this.emit('done', JSON.stringify({
    "name:": this.name,
    "time": responseTime,
    "result": this.endReason,
    "sendList": this.resultArray
  }));
}

module.exports = testSendData;
<|endoftext|>


<commit_before>/* Constants for decoding Mode S and ADS-B messages. */

/* Mode S Downlink formats
 *
 * These formats specify the length and payload format of messages from a Mode S
 * equipped aircraft to a ground station. There are short and long responses
 * defined in the protocol.
 */

var DF_TCAS_SHORT = 0;
var DF_SURV_ALTITUDE_REPLY = 4;
var DF_SURV_MODE_A_ID = 5;
var DF_ALL_CALL_REPLY = 11;
var DF_TCAS_LONG = 16;
var DF_EXT_SQUITTER = 17;
var DF_TIS_B = 18;
var DF_MIL_SQUITTER = 19;
var DF_COMM_B_ALT = 20;
var DF_COMM_B_MODE_A_ID = 21;
var DF_MILITARY = 22;
var DF_COMM_D_ELM = 24;

/* Short downlink formats are 56 bits, and consist of:
 *
 * 5 bits for the downlink format,
 * 27 bits for a surveillance and communication control word, and
 * 24 bits for a parity-encoded source address.
 */
var SHORT_DF_TYPES = [
    DF_TCAS_SHORT,
    DF_SURV_ALTITUDE_REPLY,
    DF_SURV_MODE_A_ID,
    DF_ALL_CALL_REPLY,
];

/* Long downlink formats are 112 bits, allowing for an additional message field
 * over the short downlink format. The message composition is:
 *
 * 5 bits for the downlink format,
 * 27 bits for a surveillance and communication control word,
 * 56 bits for a message, and
 * 24 bits for a parity-encoded source address.
 */
var LONG_DF_TYPES = [
    DF_TCAS_LONG,
    DF_EXT_SQUITTER,
    DF_TIS_B,
    DF_MIL_SQUITTER,
    DF_COMM_B_ALT,
    DF_COMM_B_MODE_A_ID,
    DF_MILITARY,
];

/* Extended-length downlink formats are 112 bits, just like long downlink
 * formats, but have a different structure within the message:
 *
 * 2 bits for the downlink format type,
 * 6 bits for a communication control word,
 * 80 bits for the message,
 * 24 bits for a parity-encoded source address.
 *
 * Given that three bits are sacrificed from the downlink format field to use in
 * communication control, all possible values of these three bits are included
 * in the downlink format list given the original 5-bit width.
 */
var EXTENDED_DF_TYPES = [
    DF_COMM_D_ELM,
    DF_COMM_D_ELM + 1,
    DF_COMM_D_ELM + 2,
    DF_COMM_D_ELM + 3,
    DF_COMM_D_ELM + 4,
    DF_COMM_D_ELM + 5,
    DF_COMM_D_ELM + 6,
    DF_COMM_D_ELM + 7,
];

/* Transponder capability field, used in the DF_ALL_CALL_REPLY. 3 bits.
 *
 * Values 4 through 7 are not defined in FAA 6365.1A.
 */
var CA_NO_EXTENDED_REPORT = 0;
var CA_COMM_A_B_REPORT = 1;
var CA_COMM_A_B_C_REPORT = 2;
var CA_COMM_A_B_C_D_REPORT = 3;

/* Downlink Request field, used in DF 4, 5, 20 and 21. 5 bits.
 *
 * Specifies that the aircraft has some data ready to send to the ground
 * station, and should be interrogated with the specified protocol.
 *
 * Values 2 through 15 are not defined in FAA 6365.1A.
 * Values 16 through 31 are reserved for the Comm-D protocol.
 */
var DR_NO_REQUEST = 0;
var DR_SEND_COMM_B = 1;
var DR_COMM_D_BASE = 16;

/* Flight Status field, used in DF 4, 5, 20, 21. 3 bits.
 *
 * This specifies a combination of 4 states (alert, SPI, airborne and on ground)
 * that the vehicle may be in. Please note that this is not a bitmask; the on-
 * ground and airborne state are not specified when the SPI flag is set.
 *
 * Values 6 and 7 are not specified by FAA 6365.1A.
 */
var FS_AIRBORNE = 0;
var FS_ON_GROUND = 1;
var FS_ALERT_AIRBORNE = 2;
var FS_ALERT_ON_GROUND = 3;
var FS_ALERT_SPI = 4;
var FS_SPI = 5;

/* Reply Information field.
 *
 * Values 0 through 7 are used for air-to-air interrogations, and are defined in
 * the TCAS standards.
 *
 * Values 8 through 15 are used for acquisition replies, and indicate the
 * aircraft's maximum airspeed.
 */
var RI_AIR_TO_AIR_BASE = 0;
var RI_MAX_AIRSPEED_UNKNOWN = 8;
var RI_MAX_AIRSPEED_LE_75KT = 9;
var RI_MAX_AIRSPEED_LE_150KT = 10;
var RI_MAX_AIRSPEED_LE_300KT = 11;
var RI_MAX_AIRSPEED_LE_600KT = 12;
var RI_MAX_AIRSPEED_LE_1200KT = 13;
var RI_MAX_AIRSPEED_GT_1200KT = 14;

/* Type Codes for extended squitter payloads.
 *
 * When receiving a DF_EXT_SQUITTER frame, a 5-bit number following the downlink
 * format will identify the type of data included in the message field.
 */
var TC_AIRCRAFT_IDENTIFICATION_1 = 1;
var TC_AIRCRAFT_IDENTIFICATION_2 = 2;
var TC_AIRCRAFT_IDENTIFICATION_3 = 3;
var TC_AIRCRAFT_IDENTIFICATION_4 = 4;
var TC_AIRBORNE_POSITION_9 = 9;
var TC_AIRBORNE_POSITION_10 = 10;
var TC_AIRBORNE_POSITION_11 = 11;
var TC_AIRBORNE_POSITION_12 = 12;
var TC_AIRBORNE_POSITION_13 = 13;
var TC_AIRBORNE_POSITION_14 = 14;
var TC_AIRBORNE_POSITION_15 = 15;
var TC_AIRBORNE_POSITION_16 = 16;
var TC_AIRBORNE_POSITION_17 = 17;
var TC_AIRBORNE_POSITION_18 = 18;
var TC_AIRBORNE_VELOCITY = 19;

// GNSS position
var TC_AIRBORNE_POSITION_20 = 20;
var TC_AIRBORNE_POSITION_21 = 21;
var TC_AIRBORNE_POSITION_22 = 22;

var TC_EXTENDED_SQUITTER_AC_STATUS = 28;
var TC_TARGET_STATUS = 29;
var TC_AIRCRAFT_OP_STATUS = 31;

/* Vertical Status flag. Used in TCAS responses.
 */
var VS_AIRBORNE = 0;
var VS_ON_GROUND = 1;

/* Binary Data Store register numbers.
 *
 * Avionics hardware maintains state in a set of registers known as Binary Data
 * Store registers. Typically, they are viewed as a pair of hex numbers, packed
 * together in a single byte. For example, BDS 0,5 will be addressed as 0x05,
 * and contains the position of the vehicle.
 */
var BDS_NOT_VALID = 0x00;
var BDS_UNASSIGNED = 0x01;
var BDS_COMM_B_SEGMENT_2 = 0x02;
var BDS_COMM_B_SEGMENT_3 = 0x03;
var BDS_COMM_B_SEGMENT_4 = 0x04;
var BDS_ES_AIRBORNE_POS = 0x05;
var BDS_ES_SURFACE_POS = 0x06;
var BDS_ES_STATUS = 0x07;
var BDS_ES_AC_ID_CATEGORY = 0x08;
var BDS_ES_AIRBORNE_VELOCITY = 0x09;
var BDS_ES_EVENT_REPORT = 0x0A;
var BDS_AIR_AIR_STATE = 0x0B;
var BDS_AIR_AIR_INTENT = 0x0C;
var BDS_AIR_AIR_STATE_RES1 = 0x0D;
var BDS_AIR_AIR_STATE_RES2 = 0x0E;
var BDS_ACAS_RESERVED = 0x0F;

var BDS_DATA_LINK_CAPABILITY = 0x10;
var BDS_DATA_LINK_CAP_RESERVED = 0x11;
var BDS_DATA_LINK_CAP_RESERV_2 = 0x12;
var BDS_DATA_LINK_CAP_RESERV_3 = 0x13;
var BDS_DATA_LINK_CAP_RESERV_4 = 0x14;
var BDS_DATA_LINK_CAP_RESERV_5 = 0x15;
var BDS_DATA_LINK_CAP_RESERV_6 = 0x16;
var BDS_GICB_CAPABILITY = 0x17;
var BDS_MODE_S_CAPABILITY_1 = 0x18;
var BDS_MODE_S_CAPABILITY_2 = 0x19;
var BDS_MODE_S_CAPABILITY_3 = 0x1A;
var BDS_MODE_S_CAPABILITY_4 = 0x1B;
var BDS_MODE_S_CAPABILITY_5 = 0x1C;
var BDS_MODE_S_CAPABILITY_6 = 0x1D;
var BDS_MODE_S_CAPABILITY_7 = 0x1E;
var BDS_MODE_S_CAPABILITY_8 = 0x1F;

var BDS_AIRCRAFT_IDENTITY = 0x20;
var BDS_AIRCRAFT_MARKINGS = 0x21;
var BDS_ANTENNA_POSITIONS = 0x22;
var BDS_ANTENNA_POSITION_RESERVED = 0x23;
var BDS_AIRCRAFT_PARAMS_RESERVED = 0x24;
var BDS_AIRCRAFT_TYPE = 0x25;

var BDS_ACAS_RESOLUTION = 0x30;
var BDS_VERTICAL_INTENT = 0x40;
var BDS_NEXT_WAYPOINT_ID = 0x41;
var BDS_NEXT_WAYPOINT_POS = 0x42;
var BDS_NEXT_WAYPOINT_INFO = 0x43;
var BDS_MET_AIR_REPORT = 0x44;
var BDS_MET_HAZARD_REPORT = 0x45;
var BDS_FMS_MODE_1 = 0x46;
var BDS_FMS_MODE_2 = 0x47;
var BDS_VHF_CHAN_REPORT = 0x48;

var BDS_TRACK_AND_TURN = 0x50;
var BDS_POSITION_COARSE = 0x51;
var BDS_POSITION_FINE = 0x52;
var BDS_AIR_REF_STATE = 0x53;
var BDS_WAYPOINT_1 = 0x54;
var BDS_WAYPOINT_2 = 0x55;
var BDS_WAYPOINT_3 = 0x56;
var BDS_STATIC_PARAM_MON = 0x58;

var BDS_HEADING_AND_SPEED = 0x60;
var BDS_ES_EMERGENCY_STATUS = 0x61;
var BDS_TRAJ_CHANGE_POINT = 0x62;
var BDS_NEXT_TRAJ_CHANGE_PT = 0x63;
var BDS_OPERATIONAL_COORD = 0x64;
var BDS_OPERATIONAL_STATUS = 0x65;
var BDS_MODE_S_BITE_1 = 0xE1;
var BDS_MODE_S_BITE_2 = 0xE2;
var BDS_MILITARY_1 = 0xF1;
var BDS_MILITARY_2 = 0xF2;

<commit_msg>Add transponder capability enums from DO-181C.<commit_after>/* Constants for decoding Mode S and ADS-B messages. */

/* Mode S Downlink formats
 *
 * These formats specify the length and payload format of messages from a Mode S
 * equipped aircraft to a ground station. There are short and long responses
 * defined in the protocol.
 */

var DF_TCAS_SHORT = 0;
var DF_SURV_ALTITUDE_REPLY = 4;
var DF_SURV_MODE_A_ID = 5;
var DF_ALL_CALL_REPLY = 11;
var DF_TCAS_LONG = 16;
var DF_EXT_SQUITTER = 17;
var DF_TIS_B = 18;
var DF_MIL_SQUITTER = 19;
var DF_COMM_B_ALT = 20;
var DF_COMM_B_MODE_A_ID = 21;
var DF_MILITARY = 22;
var DF_COMM_D_ELM = 24;

/* Short downlink formats are 56 bits, and consist of:
 *
 * 5 bits for the downlink format,
 * 27 bits for a surveillance and communication control word, and
 * 24 bits for a parity-encoded source address.
 */
var SHORT_DF_TYPES = [
    DF_TCAS_SHORT,
    DF_SURV_ALTITUDE_REPLY,
    DF_SURV_MODE_A_ID,
    DF_ALL_CALL_REPLY,
];

/* Long downlink formats are 112 bits, allowing for an additional message field
 * over the short downlink format. The message composition is:
 *
 * 5 bits for the downlink format,
 * 27 bits for a surveillance and communication control word,
 * 56 bits for a message, and
 * 24 bits for a parity-encoded source address.
 */
var LONG_DF_TYPES = [
    DF_TCAS_LONG,
    DF_EXT_SQUITTER,
    DF_TIS_B,
    DF_MIL_SQUITTER,
    DF_COMM_B_ALT,
    DF_COMM_B_MODE_A_ID,
    DF_MILITARY,
];

/* Extended-length downlink formats are 112 bits, just like long downlink
 * formats, but have a different structure within the message:
 *
 * 2 bits for the downlink format type,
 * 6 bits for a communication control word,
 * 80 bits for the message,
 * 24 bits for a parity-encoded source address.
 *
 * Given that three bits are sacrificed from the downlink format field to use in
 * communication control, all possible values of these three bits are included
 * in the downlink format list given the original 5-bit width.
 */
var EXTENDED_DF_TYPES = [
    DF_COMM_D_ELM,
    DF_COMM_D_ELM + 1,
    DF_COMM_D_ELM + 2,
    DF_COMM_D_ELM + 3,
    DF_COMM_D_ELM + 4,
    DF_COMM_D_ELM + 5,
    DF_COMM_D_ELM + 6,
    DF_COMM_D_ELM + 7,
];

/* Transponder capability field, used in the DF_ALL_CALL_REPLY. 3 bits.
 *
 * Values 4 through 7 are not defined in FAA 6365.1A.
 * Values 4 and above indicate the transponder is capable of at least 56 bit
 * short message transfer across down- and uplinks.
 */
var CA_NO_EXTENDED_REPORT = 0;
var CA_COMM_A_B_REPORT = 1;
var CA_COMM_A_B_C_REPORT = 2;
var CA_COMM_A_B_C_D_REPORT = 3;
var CA_MODE_S_LEVEL_2_ON_GROUND = 4;
var CA_MODE_S_LEVEL_2_AIRBORNE = 5;
var CA_MODE_S_LEVEL_2_UNKNOWN = 6;
var CA_DOWNLINK_PENDING_ALERT_OR_SPI = 7;

/* Downlink Request field, used in DF 4, 5, 20 and 21. 5 bits.
 *
 * Specifies that the aircraft has some data ready to send to the ground
 * station, and should be interrogated with the specified protocol.
 *
 * Values 2 through 15 are not defined in FAA 6365.1A.
 * Values 16 through 31 are reserved for the Comm-D protocol.
 */
var DR_NO_REQUEST = 0;
var DR_SEND_COMM_B = 1;
var DR_COMM_D_BASE = 16;

/* Flight Status field, used in DF 4, 5, 20, 21. 3 bits.
 *
 * This specifies a combination of 4 states (alert, SPI, airborne and on ground)
 * that the vehicle may be in. Please note that this is not a bitmask; the on-
 * ground and airborne state are not specified when the SPI flag is set.
 *
 * Values 6 and 7 are not specified by FAA 6365.1A.
 */
var FS_AIRBORNE = 0;
var FS_ON_GROUND = 1;
var FS_ALERT_AIRBORNE = 2;
var FS_ALERT_ON_GROUND = 3;
var FS_ALERT_SPI = 4;
var FS_SPI = 5;

/* Reply Information field.
 *
 * Values 0 through 7 are used for air-to-air interrogations, and are defined in
 * the TCAS standards.
 *
 * Values 8 through 15 are used for acquisition replies, and indicate the
 * aircraft's maximum airspeed.
 */
var RI_AIR_TO_AIR_BASE = 0;
var RI_MAX_AIRSPEED_UNKNOWN = 8;
var RI_MAX_AIRSPEED_LE_75KT = 9;
var RI_MAX_AIRSPEED_LE_150KT = 10;
var RI_MAX_AIRSPEED_LE_300KT = 11;
var RI_MAX_AIRSPEED_LE_600KT = 12;
var RI_MAX_AIRSPEED_LE_1200KT = 13;
var RI_MAX_AIRSPEED_GT_1200KT = 14;

/* Type Codes for extended squitter payloads.
 *
 * When receiving a DF_EXT_SQUITTER frame, a 5-bit number following the downlink
 * format will identify the type of data included in the message field.
 */
var TC_AIRCRAFT_IDENTIFICATION_1 = 1;
var TC_AIRCRAFT_IDENTIFICATION_2 = 2;
var TC_AIRCRAFT_IDENTIFICATION_3 = 3;
var TC_AIRCRAFT_IDENTIFICATION_4 = 4;
var TC_AIRBORNE_POSITION_9 = 9;
var TC_AIRBORNE_POSITION_10 = 10;
var TC_AIRBORNE_POSITION_11 = 11;
var TC_AIRBORNE_POSITION_12 = 12;
var TC_AIRBORNE_POSITION_13 = 13;
var TC_AIRBORNE_POSITION_14 = 14;
var TC_AIRBORNE_POSITION_15 = 15;
var TC_AIRBORNE_POSITION_16 = 16;
var TC_AIRBORNE_POSITION_17 = 17;
var TC_AIRBORNE_POSITION_18 = 18;
var TC_AIRBORNE_VELOCITY = 19;

// GNSS position
var TC_AIRBORNE_POSITION_20 = 20;
var TC_AIRBORNE_POSITION_21 = 21;
var TC_AIRBORNE_POSITION_22 = 22;

var TC_EXTENDED_SQUITTER_AC_STATUS = 28;
var TC_TARGET_STATUS = 29;
var TC_AIRCRAFT_OP_STATUS = 31;

/* Vertical Status flag. Used in TCAS responses.
 */
var VS_AIRBORNE = 0;
var VS_ON_GROUND = 1;

/* Binary Data Store register numbers.
 *
 * Avionics hardware maintains state in a set of registers known as Binary Data
 * Store registers. Typically, they are viewed as a pair of hex numbers, packed
 * together in a single byte. For example, BDS 0,5 will be addressed as 0x05,
 * and contains the position of the vehicle.
 */
var BDS_NOT_VALID = 0x00;
var BDS_UNASSIGNED = 0x01;
var BDS_COMM_B_SEGMENT_2 = 0x02;
var BDS_COMM_B_SEGMENT_3 = 0x03;
var BDS_COMM_B_SEGMENT_4 = 0x04;
var BDS_ES_AIRBORNE_POS = 0x05;
var BDS_ES_SURFACE_POS = 0x06;
var BDS_ES_STATUS = 0x07;
var BDS_ES_AC_ID_CATEGORY = 0x08;
var BDS_ES_AIRBORNE_VELOCITY = 0x09;
var BDS_ES_EVENT_REPORT = 0x0A;
var BDS_AIR_AIR_STATE = 0x0B;
var BDS_AIR_AIR_INTENT = 0x0C;
var BDS_AIR_AIR_STATE_RES1 = 0x0D;
var BDS_AIR_AIR_STATE_RES2 = 0x0E;
var BDS_ACAS_RESERVED = 0x0F;

var BDS_DATA_LINK_CAPABILITY = 0x10;
var BDS_DATA_LINK_CAP_RESERVED = 0x11;
var BDS_DATA_LINK_CAP_RESERV_2 = 0x12;
var BDS_DATA_LINK_CAP_RESERV_3 = 0x13;
var BDS_DATA_LINK_CAP_RESERV_4 = 0x14;
var BDS_DATA_LINK_CAP_RESERV_5 = 0x15;
var BDS_DATA_LINK_CAP_RESERV_6 = 0x16;
var BDS_GICB_CAPABILITY = 0x17;
var BDS_MODE_S_CAPABILITY_1 = 0x18;
var BDS_MODE_S_CAPABILITY_2 = 0x19;
var BDS_MODE_S_CAPABILITY_3 = 0x1A;
var BDS_MODE_S_CAPABILITY_4 = 0x1B;
var BDS_MODE_S_CAPABILITY_5 = 0x1C;
var BDS_MODE_S_CAPABILITY_6 = 0x1D;
var BDS_MODE_S_CAPABILITY_7 = 0x1E;
var BDS_MODE_S_CAPABILITY_8 = 0x1F;

var BDS_AIRCRAFT_IDENTITY = 0x20;
var BDS_AIRCRAFT_MARKINGS = 0x21;
var BDS_ANTENNA_POSITIONS = 0x22;
var BDS_ANTENNA_POSITION_RESERVED = 0x23;
var BDS_AIRCRAFT_PARAMS_RESERVED = 0x24;
var BDS_AIRCRAFT_TYPE = 0x25;

var BDS_ACAS_RESOLUTION = 0x30;
var BDS_VERTICAL_INTENT = 0x40;
var BDS_NEXT_WAYPOINT_ID = 0x41;
var BDS_NEXT_WAYPOINT_POS = 0x42;
var BDS_NEXT_WAYPOINT_INFO = 0x43;
var BDS_MET_AIR_REPORT = 0x44;
var BDS_MET_HAZARD_REPORT = 0x45;
var BDS_FMS_MODE_1 = 0x46;
var BDS_FMS_MODE_2 = 0x47;
var BDS_VHF_CHAN_REPORT = 0x48;

var BDS_TRACK_AND_TURN = 0x50;
var BDS_POSITION_COARSE = 0x51;
var BDS_POSITION_FINE = 0x52;
var BDS_AIR_REF_STATE = 0x53;
var BDS_WAYPOINT_1 = 0x54;
var BDS_WAYPOINT_2 = 0x55;
var BDS_WAYPOINT_3 = 0x56;
var BDS_STATIC_PARAM_MON = 0x58;

var BDS_HEADING_AND_SPEED = 0x60;
var BDS_ES_EMERGENCY_STATUS = 0x61;
var BDS_TRAJ_CHANGE_POINT = 0x62;
var BDS_NEXT_TRAJ_CHANGE_PT = 0x63;
var BDS_OPERATIONAL_COORD = 0x64;
var BDS_OPERATIONAL_STATUS = 0x65;
var BDS_MODE_S_BITE_1 = 0xE1;
var BDS_MODE_S_BITE_2 = 0xE2;
var BDS_MILITARY_1 = 0xF1;
var BDS_MILITARY_2 = 0xF2;

<|endoftext|>


<commit_before>
var width = 600,
    height = 375,
    centered;

var projection = d3.geo.albersUsa()
    .scale(800)
    .translate([width / 2, height / 2]);

var path = d3.geo.path()
    .projection(projection);

var svg = d3.select("body").append("svg")
    .attr("id", "interactive-map")
    .attr("width", width)
    .attr("height", height);

svg.append("rect")
    .attr("class", "background")
    .attr("width", width)
    .attr("height", height)
    .on("click", clicked);

var g = svg.append("g");

d3.json("us.json", function(error, us) {
  if (error) throw error;

  us.objects.states.geometries.forEach(function(element, index, array) {
    element['statecode'] = usMap[element["id"]];
  });

  g.append("g")
      .attr("id", "states")
    .selectAll("path")
      .data(topojson.feature(us, us.objects.states).features)
    .enter().append("path")
      .attr("d", path)
      .on("click", clicked);

  g.append("path")
      .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
      .attr("id", "state-borders")
      .attr("d", path);
});

function clicked(d) {
  var x, y, k;

  if (d && centered !== d) {
    var centroid = path.centroid(d);
    x = centroid[0];
    y = centroid[1];
    k = 4;
    centered = d;
  } else {
    x = width / 2;
    y = height / 2;
    k = 1;
    centered = null;
  }

  g.selectAll("path")
      .classed("active", centered && function(d) { return d === centered; });

  g.transition()
      .duration(750)
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
      .style("stroke-width", 1.5 / k + "px");
}

var usMap = {
1 : "AL",
2 : "AK",
4 : "AZ",
5 : "AR",
6 : "CA",
8 : "CO",
9 : "CT",
10  : "DE",
11  : "DC",
12  : "FL",
13  : "GA",
15  : "HI",
16  : "ID",
17  : "IL",
18  : "IN",
19  : "IA",
20  : "KS",
21  : "KY",
22  : "LA",
23  : "ME",
24  : "MD",
25  : "MA",
26  : "MI",
27  : "MN",
28  : "MS",
29  : "MO",
30  : "MT",
31  : "NE",
32  : "NV",
33  : "NH",
34  : "NJ",
35  : "NM",
36  : "NY",
37  : "NC",
38  : "ND",
39  : "OH",
40  : "OK",
41  : "OR",
42  : "PA",
44  : "RI",
45  : "SC",
46  : "SD",
47  : "TN",
48  : "TX",
49  : "UT",
50  : "VT",
51  : "VA",
53  : "WA",
54  : "WV",
55  : "WI",
56  : "WY",
60  : "AS",
64  : "FM",
66  : "GU",
68  : "MH",
69  : "MP",
70  : "PW",
72  : "PR",
74  : "UM",
78  : "VI"
};
<commit_msg>State fixes<commit_after>
var width = 600,
    height = 375,
    centered;

var projection = d3.geo.albersUsa()
    .scale(800)
    .translate([width / 2, height / 2]);

var path = d3.geo.path()
    .projection(projection);

var svg = d3.select("body").append("svg")
    .attr("id", "interactive-map")
    .attr("width", width)
    .attr("height", height);

svg.append("rect")
    .attr("class", "background")
    .attr("width", width)
    .attr("height", height)
    .on("click", clicked);

var g = svg.append("g");

d3.json("us.json", function(error, us) {
  if (error) throw error;

    var features = topojson.feature(us, us.objects.states).features;
    features.forEach(function(element, index, array) {
        element['statecode'] = usMap[element["id"]];
    });
    g.append("g")
      .attr("id", "states", 'statecode')
    .selectAll("path")
      .data(features)
    .enter().append("path")
      .attr("d", path)
      .on("click", clicked);

  g.append("path")
      .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
      .attr("id", "state-borders")
      .attr("d", path);
});

function clicked(d) {
    console.log(d.statecode);
  var x, y, k;

  if (d && centered !== d) {
    var centroid = path.centroid(d);
    x = centroid[0];
    y = centroid[1];
    k = 4;
    centered = d;
  } else {
    x = width / 2;
    y = height / 2;
    k = 1;
    centered = null;
  }

  g.selectAll("path")
      .classed("active", centered && function(d) { return d === centered; });

  g.transition()
      .duration(750)
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
      .style("stroke-width", 1.5 / k + "px");
}

var usMap = {
1 : "AL",
2 : "AK",
4 : "AZ",
5 : "AR",
6 : "CA",
8 : "CO",
9 : "CT",
10  : "DE",
11  : "DC",
12  : "FL",
13  : "GA",
15  : "HI",
16  : "ID",
17  : "IL",
18  : "IN",
19  : "IA",
20  : "KS",
21  : "KY",
22  : "LA",
23  : "ME",
24  : "MD",
25  : "MA",
26  : "MI",
27  : "MN",
28  : "MS",
29  : "MO",
30  : "MT",
31  : "NE",
32  : "NV",
33  : "NH",
34  : "NJ",
35  : "NM",
36  : "NY",
37  : "NC",
38  : "ND",
39  : "OH",
40  : "OK",
41  : "OR",
42  : "PA",
44  : "RI",
45  : "SC",
46  : "SD",
47  : "TN",
48  : "TX",
49  : "UT",
50  : "VT",
51  : "VA",
53  : "WA",
54  : "WV",
55  : "WI",
56  : "WY",
60  : "AS",
64  : "FM",
66  : "GU",
68  : "MH",
69  : "MP",
70  : "PW",
72  : "PR",
74  : "UM",
78  : "VI"
};
<|endoftext|>


<commit_before>define(
  'ephox.snooker.resize.BarPositions',

  [
    'ephox.compass.Arr',
    'ephox.peanut.Fun',
    'ephox.scullion.Struct',
    'ephox.sugar.api.Height',
    'ephox.sugar.api.Location',
    'ephox.sugar.api.Width'
  ],

  function (Arr, Fun, Struct, Height, Location, Width) {
    var rowInfo = Struct.immutable('row', 'y');
    var colInfo = Struct.immutable('col', 'x');

    var ltrPositions = function (cols, _table) {
      if (cols.length === 0 ) return [];
      var lines = Arr.map(cols.slice(1), function (cellOption, col) {
        return cellOption.map(function (cell) {
          var pos = Location.absolute(cell);
          return colInfo(col, pos.left());
        });
      });

      var lastLine = cols[cols.length - 1].map(function (lastCol) {
        var lastX = Location.absolute(lastCol).left() + Width.getOuter(lastCol);
        return colInfo(cols.length - 1, lastX);
      });

      return lines.concat([ lastLine ]);
    };

    var rtlPositions = function (cols, _table) {
      if (cols.length === 0 ) return [];
      var lines = Arr.map(cols.slice(1), function (cellOption, col) {
        return cellOption.map(function (cell) {
          var pos = Location.absolute(cell  );
          return colInfo(col, pos.left() + Width.getOuter(cell));
        });
      });

      var lastLine = cols[cols.length - 1].map(function (lastCol) {
        var lastX = Location.absolute(lastCol).left();
        return colInfo(cols.length - 1, lastX);
      });

      return lines.concat([ lastLine ]);
    };

    var rtlEdge = function (cell) {
      var pos = Location.absolute(cell);
      return pos.left() + Width.getOuter(cell);
    };

    var ltrEdge = function (cell) {
      return Location.absolute(cell).left();
    };

    var negate = function (step, _table) {
      return -step;
    };

    var heightPositions = function (rows, _table) {
      if (rows.length === 0 ) return [];
      var lines = Arr.map(rows.slice(1), function (cellOption, row) {
        return cellOption.map(function (cell) {
          var pos = Location.absolute(cell);
          return rowInfo(row, pos.top());
        });
      });

      var lastLine = rows[rows.length - 1].map(function (lastRow) {
        var lastY = Location.absolute(lastRow).top() + Height.getOuter(lastRow);
        return rowInfo(rows.length - 1, lastY);
      });

      return lines.concat( [ lastLine ] );
    };

    var heightEdge = function (cell) {
      return Location.absolute(cell).top();
    };

    var height = {
      delta: Fun.identity,
      positions: heightPositions,
      edge: heightEdge
    };

    var ltr = {
      delta: Fun.identity,
      edge: ltrEdge,
      positions: ltrPositions
    };

    var rtl = {
      delta: negate,
      edge: rtlEdge,
      positions: rtlPositions
    };

    return {
      height: height,
      rtl: rtl,
      ltr: ltr
    };
  }
);<commit_msg>TBIO-2529: Bar positions<commit_after>define(
  'ephox.snooker.resize.BarPositions',

  [
    'ephox.compass.Arr',
    'ephox.peanut.Fun',
    'ephox.scullion.Struct',
    'ephox.sugar.api.Height',
    'ephox.sugar.api.Location',
    'ephox.sugar.api.Width'
  ],

  function (Arr, Fun, Struct, Height, Location, Width) {
    var rowInfo = Struct.immutable('row', 'y');
    var colInfo = Struct.immutable('col', 'x');

    var rtlEdge = function (cell) {
      var pos = Location.absolute(cell);
      return pos.left() + Width.getOuter(cell);
    };

    var ltrEdge = function (cell) {
      return Location.absolute(cell).left();
    };

    var getLeftEdge = function (index, cell) {
      return colInfo(index, ltrEdge(cell));
    };

    var getRightEdge = function (index, cell) {
      return colInfo(index, rtlEdge(cell));
    };

    var getTop = function (cell) {
      return Location.absolute(cell).top();
    };

    var getTopEdge = function (index, cell) {
      return rowInfo(index, getTop(cell));
    };

    var getBottomEdge = function (index, cell) {
      return rowInfo(index, getTop(cell) + Height.getOuter(cell));
    };

    var findPositions = function (getInnerEdge, getOuterEdge, array) {
      if (array.length === 0 ) return [];
      var lines = Arr.map(array.slice(1), function (cellOption, index) {
        return cellOption.map(function (cell) {
          return getInnerEdge(index, cell);
        });
      });

      var lastLine = array[array.length - 1].map(function (cell) {
        return getOuterEdge(array.length - 1, cell);
      });

      return lines.concat([ lastLine ]);
    };

    var negate = function (step, _table) {
      return -step;
    };

    var height = {
      delta: Fun.identity,
      positions: Fun.curry(findPositions, getTopEdge, getBottomEdge),
      edge: getTop
    };

    var ltr = {
      delta: Fun.identity,
      edge: ltrEdge,
      positions: Fun.curry(findPositions, getLeftEdge, getRightEdge)
    };

    var rtl = {
      delta: negate,
      edge: rtlEdge,
      positions: Fun.curry(findPositions, getRightEdge, getLeftEdge)
    };

    return {
      height: height,
      rtl: rtl,
      ltr: ltr
    };
  }
);<|endoftext|>


<commit_before>var WATCH_JSON_LIST =
[
	[110000, 28501],
[772],
	[6060],
	[451],
	[221004],
	[110010],
	[700],
	[5, 17602],
	[175],
	[1211, 16904],
	[1918],
	[1919],
	[2777],
	[3333],
	[1],
	[388],
	[3988],
	[293],
	[1523],
	[802],
	[1150],
	[1165],
	[3800]
];
<commit_msg>Update watch-list.js<commit_after>var WATCH_JSON_LIST =
[
	[110000, 28501],
[772],
	[6060],
	[451],
	[221004],
	[110010],
	[700],
	[5],
	[175],
	[1211, 16904],
	[1918],
	[1919],
	[2777],
	[3333],
	[1],
	[388],
	[3988],
	[293],
	[1523],
	[802],
	[1150],
	[1165],
	[3800]
];
<|endoftext|>


<commit_before>// --------------------
// Default resource controller
// index action
// --------------------

// modules
var Promise = require('bluebird-extra'),
	_ = require('overlook-utils');

// libraries
var forms = require('../../../../lib/forms');

// exports

// action definition
exports = module.exports = {
	// variables

	sortDefault: 'name',

	// functions

	init: function(defaultFn) {
		return defaultFn().bind(this)
		.then(function() {
			// make fields
			this.fields = forms.createFieldsFromModel(this.route.model);

			// make form
			this.form = forms.createFormFromModel(this.route.model);
			_.moveValue(this, this.form, 'loadReferences');
			delete this.form;
		});
	},

	start: function() {
		// get paging + sorting
		this.paging = {page: this.query.p * 1 || 1};

		// create sort order
		this.sort = this.query.s;
		if (this.sort === undefined) this.sort = this.sortDefault;

		// create filters
		this.filters = {};
		_.forIn(this.query, function(value, attribute) {
			if (_.startsWith(attribute, 'f')) this.filters[_.uncapitalize(attribute.slice(1))] = value;
		}, this);
	},

	load: function(defaultFn) {
		return defaultFn().bind(this)
		.then(this.loaded)
		.ifElse(function() {
			// set up options
			var options = {
				where: {},
				include: [{all: 'One', attributes: ['id', 'name']}]
			};

			// set filters
			_.forIn(this.filters, function(value, attribute) {
				var field = this.fields[attribute];
				if (field) {
					if (field.mainType == 'string') {
						options.where[attribute] = {like: '%' + value + '%'};
					} else if (field.mainType == 'date') {
						value = forms.conformers.date(value);
						this.filters[attribute] = _.dateToString(value);
						options.where[attribute] = {gte: value};
					} else {
						options.where[attribute] = value;
					}
				} else if (_.endsWith(attribute, 'Name')) {
					field = this.fields[attribute.slice(0, -4) + 'Id'];
					if (field && field.reference) options.where[attribute.slice(0, -4) + '.name'] = {like: '%' + value + '%'};
				}
			}, this);

			// set sort order
			if (this.sort) {
				var order;
				var attribute = this.sort;
				if (_.startsWith(attribute, '-')) {
					attribute = attribute.slice(1);
					order = [attribute, 'DESC'];
				} else {
					order = [attribute, 'ASC'];
				}

				var reference = this.model.rawAttributes[attribute] && this.model.rawAttributes[attribute].reference;
				if (reference) {
					var as = attribute.slice(0, -2);
					if (as != reference) {
						order.unshift({model: this.models[reference], as: as});
					} else {
						order.unshift(this.models[reference]);
					}
					order[1] = 'name';
				}

				options.order = [order];
			} else {
				options.order = [];
			}
			options.order.push(['id', 'ASC']);

			// set paging
			var pageLength = this.overlook.options.general.pageLength;
			options.limit = pageLength;
			options.offset = pageLength * (this.paging.page - 1);

			// filter by parent resources
			if (this.parentResources) {
				var parentResource = this.parentResources[this.parentResources.length - 1];
				options.where[parentResource.model.name + _.capitalize(parentResource.paramField)] = this.params[parentResource.param];
			}

			// get from db
			return this.model.findAndCountAll(options).bind(this)
			.then(function(result) {
				this.paging.pages = Math.ceil(result.count / pageLength);

				// save db result to data
				this.dataMain = this.data[this.model.namePlural] = result.rows;
			});
		});
	},

	makeDisplayOptions: function(defaultFn) {
		return defaultFn().bind(this)
		.then(function() {
			var viewData = this.displayOptions.options.data = {};
			viewData[this.model.namePlural] = forms.getValuesByFields(this.dataMain, _.extend({id: {}}, this.fields));

			_.forEach(this.loadReferences, function(model) {
				viewData[model.namePlural] = forms.getValuesByFields(this.data[model.namePlural], {id: {}, name: {}});
			}, this);

			// put filters in display options, including filling in Name fields for open menus
			this.displayOptions.options.filters = this.filters;
			var filterNames = this.displayOptions.options.filterNames = {};

			return Promise.in(this.fields, function(field, fieldName) {
				if (field.widget != 'menuOpen') return;
				if (!this.filters[fieldName]) return;

				var referenceName = fieldName.slice(0, -2);
				var nameFieldName = referenceName + 'Name';
				if (this.filters[nameFieldName]) return;

				if (this.dataMain.length) {
					filterNames[nameFieldName] = this.dataMain[0][referenceName].name;
					return;
				}

				return this.models[referenceName].find({where: {id: this.filters[fieldName]}, attributes: ['name']}).bind(this)
				.then(function(item) {
					filterNames[nameFieldName] = item.name;
				});
			}.bind(this)).bind(this)
			.then(function() {
				this.displayOptions.options.sort = this.sort;
				this.displayOptions.options.sortDefault = this.sortDefault;
				this.displayOptions.options.paging = this.paging;
			});
		});
	}
};
<commit_msg>Move load options building into own function<commit_after>// --------------------
// Default resource controller
// index action
// --------------------

// modules
var Promise = require('bluebird-extra'),
	_ = require('overlook-utils');

// libraries
var forms = require('../../../../lib/forms');

// exports

// action definition
exports = module.exports = {
	// variables

	sortDefault: 'name',

	// functions

	init: function(defaultFn) {
		return defaultFn().bind(this)
		.then(function() {
			// make fields
			this.fields = forms.createFieldsFromModel(this.route.model);

			// make form
			this.form = forms.createFormFromModel(this.route.model);
			_.moveValue(this, this.form, 'loadReferences');
			delete this.form;
		});
	},

	start: function() {
		// get paging + sorting
		this.paging = {page: this.query.p * 1 || 1};

		// create sort order
		this.sort = this.query.s;
		if (this.sort === undefined) this.sort = this.sortDefault;

		// create filters
		this.filters = {};
		_.forIn(this.query, function(value, attribute) {
			if (_.startsWith(attribute, 'f')) this.filters[_.uncapitalize(attribute.slice(1))] = value;
		}, this);
	},

	load: function(defaultFn) {
		return defaultFn().bind(this)
		.then(this.loaded)
		.ifElse(function() {
			// set up options
			var options = {include: {all: 'One', attributes: ['id', 'name']}};
			this.loadOptions.call(this, options);

			// filter by parent resources
			if (this.parentResources) {
				var parentResource = this.parentResources[this.parentResources.length - 1];
				options.where[parentResource.model.name + _.capitalize(parentResource.paramField)] = this.params[parentResource.param];
			}

			// get from db
			return this.model.findAndCountAll(options).bind(this)
			.then(function(result) {
				this.paging.pages = Math.ceil(result.count / options.limit);

				// save db result to data
				this.dataMain = this.data[this.model.namePlural] = result.rows;
			});
		});
	},

	loadOptions: function(options) {
		// set filters
		options.where = {};

		_.forIn(this.filters, function(value, attribute) {
			var field = this.fields[attribute];
			if (field) {
				if (field.mainType == 'string') {
					options.where[attribute] = {like: '%' + value + '%'};
				} else if (field.mainType == 'date') {
					value = forms.conformers.date(value);
					this.filters[attribute] = _.dateToString(value);
					options.where[attribute] = {gte: value};
				} else {
					options.where[attribute] = value;
				}
			} else if (_.endsWith(attribute, 'Name')) {
				field = this.fields[attribute.slice(0, -4) + 'Id'];
				if (field && field.reference) options.where[attribute.slice(0, -4) + '.name'] = {like: '%' + value + '%'};
			}
		}, this);

		// set sort order
		if (this.sort) {
			var order;
			var attribute = this.sort;
			if (_.startsWith(attribute, '-')) {
				attribute = attribute.slice(1);
				order = [attribute, 'DESC'];
			} else {
				order = [attribute, 'ASC'];
			}

			var reference = this.model.rawAttributes[attribute] && this.model.rawAttributes[attribute].reference;
			if (reference) {
				var as = attribute.slice(0, -2);
				if (as != reference) {
					order.unshift({model: this.models[reference], as: as});
				} else {
					order.unshift(this.models[reference]);
				}
				order[1] = 'name';
			}

			options.order = [order];
		} else {
			options.order = [];
		}

		options.order.push(['id', 'ASC']);

		// set paging
		var pageLength = this.overlook.options.general.pageLength;
		options.limit = pageLength;
		options.offset = pageLength * (this.paging.page - 1);
	},

	makeDisplayOptions: function(defaultFn) {
		return defaultFn().bind(this)
		.then(function() {
			var viewData = this.displayOptions.options.data = {};
			viewData[this.model.namePlural] = forms.getValuesByFields(this.dataMain, _.extend({id: {}}, this.fields));

			_.forEach(this.loadReferences, function(model) {
				viewData[model.namePlural] = forms.getValuesByFields(this.data[model.namePlural], {id: {}, name: {}});
			}, this);

			// put filters in display options, including filling in Name fields for open menus
			this.displayOptions.options.filters = this.filters;
			var filterNames = this.displayOptions.options.filterNames = {};

			return Promise.in(this.fields, function(field, fieldName) {
				if (field.widget != 'menuOpen') return;
				if (!this.filters[fieldName]) return;

				var referenceName = fieldName.slice(0, -2);
				var nameFieldName = referenceName + 'Name';
				if (this.filters[nameFieldName]) return;

				if (this.dataMain.length) {
					filterNames[nameFieldName] = this.dataMain[0][referenceName].name;
					return;
				}

				return this.models[referenceName].find({where: {id: this.filters[fieldName]}, attributes: ['name']}).bind(this)
				.then(function(item) {
					filterNames[nameFieldName] = item.name;
				});
			}.bind(this)).bind(this)
			.then(function() {
				this.displayOptions.options.sort = this.sort;
				this.displayOptions.options.sortDefault = this.sortDefault;
				this.displayOptions.options.paging = this.paging;
			});
		});
	}
};
<|endoftext|>


<commit_before>$(document).ready(function(){

    /// INLINE ELEMENTS
    /// collapsible elements for stacked inlines
    $('div.inline-stacked div.inline-related').each(function(i) {
        $(this).addClass("collapsed");
        $(this).find('h3:first').attr("class", "collapse-toggle");
    });
    $('div.inline-stacked div.inline-related h3.collapse-toggle').bind("click", function(){
        $(this).parent().toggleClass('collapsed');
    });

    /// INLINEGROUPS (STACKED & TABULAR)
    $('div.inline-group.collapse-closed').each(function() {
        $(this).addClass("collapsed");
        $(this).find('h2:first').attr("class", "collapse-toggle");
    });
    $('div.inline-group.collapse-open').each(function() {
        $(this).find('h2:first').attr("class", "collapse-toggle");
    });
    $('div.inline-group h2.collapse-toggle').bind("click", function(){
        $(this).parent().toggleClass('collapsed');
    });

    /// OPEN STACKEDINLINE WITH ERRORS
    $('div.inline-stacked div.inline-related').find('div[class*="errors"]:first').each(function(){
        $(this).parent().parent().toggleClass("collapsed");
    });
    $('div.inline-stacked').find('div[class*="errors"]:first').each(function(){
        /// open inline group
        $(this).parent().parent().parent().parent().toggleClass("collapsed");
    });

    /// OPEN TABULARINLINE WITH ERRORS
    $('div.inline-tabular').find('div[class*="error"]:first').each(function(i) {
        $(this).parents('div.inline-tabular').removeClass("collapsed");
    });

});
<commit_msg>update: stacked inlines with errors should now be opened correctly<commit_after>$(document).ready(function(){

    /// INLINE ELEMENTS
    /// collapsible elements for stacked inlines
    $('div.inline-stacked div.inline-related').each(function(i) {
        $(this).addClass("collapsed");
        $(this).find('h3:first').attr("class", "collapse-toggle");
    });
    $('div.inline-stacked div.inline-related h3.collapse-toggle').bind("click", function(){
        $(this).parent().toggleClass('collapsed');
    });

    /// INLINEGROUPS (STACKED & TABULAR)
    $('div.inline-group.collapse-closed').each(function() {
        $(this).addClass("collapsed");
        $(this).find('h2:first').attr("class", "collapse-toggle");
    });
    $('div.inline-group.collapse-open').each(function() {
        $(this).find('h2:first').attr("class", "collapse-toggle");
    });
    $('div.inline-group h2.collapse-toggle').bind("click", function(){
        $(this).parent().toggleClass('collapsed');
    });

    /// OPEN STACKEDINLINE WITH ERRORS
    $('div.inline-stacked div.inline-related').find('div[class*="errors"]:first').each(function(){
        $(this).parents('div.inline-related').removeClass("collapsed");
        $(this).parents('div.inline-stacked').removeClass("collapsed");
    });

    /// OPEN TABULARINLINE WITH ERRORS
    $('div.inline-tabular').find('div[class*="error"]:first').each(function(i) {
        $(this).parents('div.inline-tabular').removeClass("collapsed");
    });

});
<|endoftext|>