<commit_before>/* @flow strict-local */
import type { SeverityType, EventHint } from '@sentry/react-native';
import { getCurrentHub, Severity } from '@sentry/react-native';

import config from '../config';

/**
 * Log an event (a string or Error) at some arbitrary severity.
 *
 * The error will be logged to Sentry, including a stack trace. The stack trace
 * is taken from `err` if an `Error` object, and otherwise synthesized from the
 * call site.
 *
 * Returns a Sentry event_id, although this is not expected to be useful.
 */
const logToSentry = (event: string | Error, level: SeverityType): string => {
  let message: string;
  let hint: EventHint;

  if (event instanceof Error) {
    // eslint-disable-next-line prefer-destructuring
    message = event.message;
    hint = { originalException: event };
  } else {
    // Synthesize the event's stack trace. (The static API does this for us, at
    // least sometimes; but we're calling in at one level lower.)
    message = event;
    try {
      throw new Error(event);
    } catch (err) {
      hint = { syntheticException: err };
    }
  }

  // The static API's `captureException` doesn't allow passing strings, and its
  // counterpart `captureMessage` doesn't allow passing stacktraces.
  // Fortunately, the quasi-internal "Hub" API exists, and is reasonably
  // well-documented:
  //
  // https://docs.sentry.io/development/sdk-dev/unified-api/#hub
  //
  // (There is a `captureEvent` method that allows both explicitly; but it also
  // expects a great deal of other information which we would have to
  // synthesize, and which has no user-facing documentation.)
  return getCurrentHub().captureMessage(message, level, hint);
};

type LogParams = {|
  consoleMethod: mixed => void,
  severity: SeverityType,
|};
type LogFunction = (event: string | Error) => void;

const makeLogFunction = ({ consoleMethod, severity }: LogParams): LogFunction => {
  const toConsole = consoleMethod.bind(console);

  return (event: string | Error) => {
    logToSentry(event, severity);

    if (config.enableErrorConsoleLogging) {
      toConsole(event);
    }
  };
};

/* eslint-disable no-console */

// Notes on the behavior of `console.error`, `console.warn`, `console.log`:
//
// * When debugging JS: all display in the Chrome dev console, and not in
//   the Android system log.
//   * `error` and `warn` produce a nice expando-hidden stack trace, in
//     addition to formatting their arguments.
//   * `log` just formats the arguments.
//   * An `Error` argument formats with its embedded stack trace.  (As just
//     text, with no spiffy expando.)
//
// * In a debug build, whether debugging JS or not:
//   * `error` pops up the RN error red-screen.
//   * `warn` could pop up an RN yellow-box, but we've set
//     `console.disableYellowBox` so it doesn't.
//
// * On Android, on both debug and release builds, except when debugging JS:
//   * All of `error`, `warn`, `log` go to the system log (for `adb logcat`).
//   * An `Error` argument formats with (the name + message and) just the
//     single source location where it was created, no stack trace.

/**
 * Log an error at "error" severity.
 *
 * The error will be logged to Sentry and/or the console as appropriate.
 *
 * In a debug build, this pops up the RN error red-screen.  This is
 * appropriate when the condition should never happen and definitely
 * represents a bug.  For conditions that can happen without a bug (e.g. a
 * failure to reach the server), consider `logging.warn`.
 *
 * @param event A string describing the nature of the event to be logged, or an
 *   exception whose `.message` is such a string. Related events should have
 *   identical such strings, when feasible.
 *
 * See also:
 *  * `logging.warn` for logging at lower severity
 */
export const error: (event: string | Error) => void = makeLogFunction({
  consoleMethod: console.error,
  severity: Severity.Error,
});

/**
 * Log an event at "warning" severity.
 *
 * The event will be logged to Sentry and/or the console as appropriate.
 *
 * In the JS debugging console, this produces a yellow-highlighted warning,
 * but no popup interruption.  This makes it appropriate for conditions
 * which have an inevitable background rate.  For conditions which
 * definitely represent a bug in the app, consider `logging.error` instead.
 *
 * @param event A string describing the nature of the event to be logged, or an
 *   exception whose `.message` is such a string. Related events should have
 *   identical such strings, when feasible.
 *
 * See also:
 *  * `logging.error` for logging at higher severity
 */
export const warn: (event: string | Error) => void = makeLogFunction({
  consoleMethod: console.warn,
  severity: Severity.Warning,
});
<commit_msg>logging [nfc]: add Sentry "extras" support<commit_after>/* @flow strict-local */
import type { Scope, SeverityType, EventHint } from '@sentry/react-native';
import { getCurrentHub, Severity, withScope as withScopeImpl } from '@sentry/react-native';

import config from '../config';

type Extras = { [key: string]: mixed };

// Wrapper for `Sentry.withScope`, allowing callbacks to return values.
function withScope<R>(callback: Scope => R): R {
  let ret: R;
  withScopeImpl(scope => {
    ret = callback(scope);
  });
  // Flow can't know that `ret` has actually been initialized
  return ((ret: $FlowFixMe): R);
}

/**
 * Log an event (a string or Error) at some arbitrary severity.
 *
 * The error will be logged to Sentry, including a stack trace. The stack trace
 * is taken from `err` if an `Error` object, and otherwise synthesized from the
 * call site.
 *
 * Returns a Sentry event_id, although this is not expected to be useful.
 */
const logToSentry = (event: string | Error, level: SeverityType, extras: Extras): string => {
  let message: string;
  let hint: EventHint;

  if (event instanceof Error) {
    // eslint-disable-next-line prefer-destructuring
    message = event.message;
    hint = { originalException: event };
  } else {
    // Synthesize the event's stack trace. (The static API does this for us, at
    // least sometimes; but we're calling in at one level lower.)
    message = event;
    try {
      throw new Error(event);
    } catch (err) {
      hint = { syntheticException: err };
    }
  }

  return withScope(scope => {
    scope.setExtras(extras);

    // The static API's `captureException` doesn't allow passing strings, and its
    // counterpart `captureMessage` doesn't allow passing stacktraces.
    // Fortunately, the quasi-internal "Hub" API exists, and is reasonably
    // well-documented:
    //
    // https://docs.sentry.io/development/sdk-dev/unified-api/#hub
    //
    // (There is a `captureEvent` method that allows both explicitly; but it also
    // expects a great deal of other information which we would have to
    // synthesize, and which has no user-facing documentation.)
    return getCurrentHub().captureMessage(message, level, hint);
  });
};

type LogParams = {|
  consoleMethod: mixed => void,
  severity: SeverityType,
|};
type LogFunction = (event: string | Error, extras?: Extras) => void;

const makeLogFunction = ({ consoleMethod, severity }: LogParams): LogFunction => {
  const toConsole = consoleMethod.bind(console);

  return (event: string | Error, extras: Extras = {}) => {
    logToSentry(event, severity, extras);

    if (config.enableErrorConsoleLogging) {
      toConsole(event);

      const data = Object.entries(extras)
        .map(([key, value]) => `    ${key}: ${JSON.stringify(value)}`)
        .join('\n');

      if (data) {
        toConsole(data);
      }
    }
  };
};

/* eslint-disable no-console */

// Notes on the behavior of `console.error`, `console.warn`, `console.log`:
//
// * When debugging JS: all display in the Chrome dev console, and not in
//   the Android system log.
//   * `error` and `warn` produce a nice expando-hidden stack trace, in
//     addition to formatting their arguments.
//   * `log` just formats the arguments.
//   * An `Error` argument formats with its embedded stack trace.  (As just
//     text, with no spiffy expando.)
//
// * In a debug build, whether debugging JS or not:
//   * `error` pops up the RN error red-screen.
//   * `warn` could pop up an RN yellow-box, but we've set
//     `console.disableYellowBox` so it doesn't.
//
// * On Android, on both debug and release builds, except when debugging JS:
//   * All of `error`, `warn`, `log` go to the system log (for `adb logcat`).
//   * An `Error` argument formats with (the name + message and) just the
//     single source location where it was created, no stack trace.

/**
 * Log an error at "error" severity.
 *
 * The error will be logged to Sentry and/or the console as appropriate.
 *
 * In a debug build, this pops up the RN error red-screen.  This is
 * appropriate when the condition should never happen and definitely
 * represents a bug.  For conditions that can happen without a bug (e.g. a
 * failure to reach the server), consider `logging.warn`.
 *
 * @param event A string describing the nature of the event to be logged, or an
 *   exception whose `.message` is such a string. Related events should have
 *   identical such strings, when feasible.
 * @param extras Diagnostic data which may differ between separate occurrences
 *   of the event.
 *
 * See also:
 *  * `logging.warn` for logging at lower severity
 */
export const error: (event: string | Error, extras?: Extras) => void = makeLogFunction({
  consoleMethod: console.error,
  severity: Severity.Error,
});

/**
 * Log an event at "warning" severity.
 *
 * The event will be logged to Sentry and/or the console as appropriate.
 *
 * In the JS debugging console, this produces a yellow-highlighted warning,
 * but no popup interruption.  This makes it appropriate for conditions
 * which have an inevitable background rate.  For conditions which
 * definitely represent a bug in the app, consider `logging.error` instead.
 *
 * @param event A string describing the nature of the event to be logged, or an
 *   exception whose `.message` is such a string. Related events should have
 *   identical such strings, when feasible.
 * @param extras Diagnostic data which may differ between separate occurrences
 *   of the event.
 *
 * See also:
 *  * `logging.error` for logging at higher severity
 */
export const warn: (event: string | Error, extras?: Extras) => void = makeLogFunction({
  consoleMethod: console.warn,
  severity: Severity.Warning,
});
<|endoftext|>


<commit_before>/************************************************************************
 * Set settings using the settings sidebar.  Also sets settings on bind *
 ************************************************************************/

Worksheet.open(function(_) {
	var default_settings = { angle: 'rad', complex: 'on', units: 'mks', digits: '9', custom_units: false, base_units: ['m','kg','s','K'], derived_units: ['A','mol','cd','E','N','Ohm','Pa','J','T','C','F','H','Hz','V','W','Wb'] };
	var showApplyNow = function() {
		$('.popup_dialog .bottom_links button.submit').show();
	}
	_.setSettingsText = function() {
		var out = "";
		out += this.settings.angle == 'rad' ? 'Rad' : 'Deg';
		out += ", ";
		out += this.settings.complex == 'on' ? 'Complex' : 'Real';
		out += ", ";
		out += this.settings.digits;
		out += " digits, " + this.settings.base_units[0] + ', ' + this.settings.base_units[1] + ', ' + this.settings.base_units[2] + ', ' + this.settings.base_units[3];
		return out;
	}
	var settingsHTML = "
"
			+ "
 Worksheet Settings
"
			+ "
"
			+ "Angle Mode: "
			+ "
<select class='angle_mode' data-type='angle_mode'>"
			+ "<option value='rad'>Radians</option>"
			+ "<option value='deg'>Degrees</option>"
			+ "</select>
"
			+ "
"
			+ "
"
			+ "Complex Mode: "
			+ "
<select class='complex_mode' data-type='complex_mode'>"
			+ "<option value='on'>Enabled</option>"
			+ "<option value='off'>Disabled</option>"
			+ "</select>
"
			+ "
"
			+ "
"
			+ "Significant Digits: "
			+ "
<select class='digits_select' data-type='digits_select'>"
			+ "<option value='1'>1</option>"
			+ "<option value='2'>2</option>"
			+ "<option value='3'>3</option>"
			+ "<option value='4'>4</option>"
			+ "<option value='5'>5</option>"
			+ "<option value='6'>6</option>"
			+ "<option value='7'>7</option>"
			+ "<option value='8'>8</option>"
			+ "<option value='9'>9</option>"
			+ "<option value='10'>10</option>"
			+ "<option value='11'>11</option>"
			+ "<option value='12'>12</option>"
			+ "<option value='13'>13</option>"
			+ "<option value='14'>14</option>"
			+ "</select>
"
			+ "
"
			+ "
"
			+ "Unit System: "
			+ "
<select class='unit_mode' data-type='unit_mode'>"
			+ "<option value='mks'>Meters-Kilograms-Seconds</option>"
			+ "<option value='cgs'>Centimeter-Grams-Seconds</option>"
			+ "<option value='ips'>Inch-Pounds-Seconds</option>"
			+ "</select>"
			+ "
customize
"
			+ "
"
			+ "
"
			+ "
Base Units
"
			+ "

"
			+ "
Length:
"
			+ "
Mass:
"
			+ "
Time:
"
			+ "
Temperature:
"
			+ "

"
			+ "
Derived Units
"
			+ "
"
			+ "Derived units are combinations of base units.  For example, force is mass * length / time^2, but we often express in its own unit for simplicity.  Add derived units to the list below.  When found in answer, base units will be auto-simplified to the derived equivalent."
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
";
	var setUnitSidebar = function(_this) {
		if((_this.settings.custom_units == "true") || (_this.settings.custom_units ===true)) {
	    $('div.custom_units').addClass('shown');
	    $('a.custom_units').hide();
		} else {
	    $('a.custom_units').show();
	    $('div.custom_units').removeClass('shown');
		}
		$('div.custom_units span.length').html('' + _this.latexToHtml("\\Unit{" + _this.settings.base_units[0] + "}") + '');
		$('div.custom_units span.mass').html('' + _this.latexToHtml("\\Unit{" + _this.settings.base_units[1] + "}") + '');
		$('div.custom_units span.time').html('' + _this.latexToHtml("\\Unit{" + _this.settings.base_units[2] + "}") + '');
		$('div.custom_units span.temp').html('' + _this.latexToHtml("\\Unit{" + _this.settings.base_units[3] + "}") + '');
		$('div.custom_units .added_units').html('');
		for(var i = 0; i < _this.settings.derived_units.length; i++) {
			$('
').addClass('derived_unit').html('' + _this.latexToHtml("\\Unit{" + _this.settings.derived_units[i] + "}") + '').appendTo($('div.custom_units .added_units'));
		}
		$('div.custom_units .added_units i.fa-times').on('click', function(e) {
			$(this).closest('.derived_unit').remove();
			_this.buildUnitSettings();
			e.preventDefault();
			e.stopPropagation();
			return false;
		})
		var mq_onblur = function(_this) {
			return function(mq) {
				$('span.standalone_textarea').remove();
				var jQ = mq.jQ;
				var unit = mq.latex();
				var unit_text = mq.text().replace(/_/g,'');
				if(!unit_text.match(/^[a-z2µ]+$/i)) {
					showNotice('Unit settings should only be single units (m, N, Pa, etc), not combined units (m/s).', 'red');
					unit_text = unit.replace(/^\\Unit\{(.*)\}$/,"$1");
				} else {
					showApplyNow();
				}
				mq.revert();
				jQ.html('');
				var span = $('').addClass('custom_unit_box');
				span.attr('data-unit', unit_text);
				jQ.append(span);
				_this.buildUnitSettings();
			}
		}
		$('span.custom_unit_box').on('click', function(e) {
			var span = $('').addClass('choose_unit').appendTo($(this).parent());
			var mq = window.standaloneMathquill(span, false, true, { blur: mq_onblur(_this) });
			mq.setUnitsOnly(true);
			mq.write("\\Unit{" + $(this).attr('data-unit') + "}");
			//mq.focus();
			mq.keystroke("Left", {preventDefault: function() {} });
			$(this).remove();
		});
	}
	_.buildUnitSettings = function() {
		this.settings.base_units[0] = $('div.custom_units span.length .custom_unit_box').attr('data-unit');
		this.settings.base_units[1] = $('div.custom_units span.mass .custom_unit_box').attr('data-unit');
		this.settings.base_units[2] = $('div.custom_units span.time .custom_unit_box').attr('data-unit');
		this.settings.base_units[3] = $('div.custom_units span.temp .custom_unit_box').attr('data-unit');
		this.settings.derived_units = [];
		var _this = this;
		$('div.custom_units .added_units .custom_unit_box').each(function() {
			_this.settings.derived_units.push($(this).attr('data-unit'));
		});
		this.settings.custom_units = $('div.custom_units').hasClass('shown');
		setUnitSidebar(this);
	}
	var handleSelectChange = function(e) {
		switch($(this).attr('data-type')) {
			case 'angle_mode':
				SwiftCalcs.active_worksheet.settings.angle = $(this).val();
				break;
			case 'complex_mode':
				SwiftCalcs.active_worksheet.settings.complex = $(this).val();
				break;
			case 'digits_select':
				SwiftCalcs.active_worksheet.settings.digits = $(this).val();
				break;
			case 'unit_mode':
				SwiftCalcs.active_worksheet.settings.units = $(this).val();
				switch(SwiftCalcs.active_worksheet.settings.units) {
					case 'mks':
						var base = ['m','kg','s','K'];
						var derived = ['A','mol','cd','E','N','Ohm','Pa','J','T','C','F','H','Hz','V','W','Wb'];
						break;
					case 'cgs':
						var base = ['cm','g','s','K'];
						var derived = ['mL','A','mol','cd','E','N','Ohm','Pa','J','T','C','F','H','Hz','V','W','Wb'];
						break;
					case 'ips':
						var base = ['in','lb','s','Rankine'];
						var derived = ['gal','A','mol','cd','E','lbf','Ohm','psi','Btu','T','C','F','H','Hz','V','hp','Wb'];
						break;
				}
				SwiftCalcs.active_worksheet.settings.base_units = base;
				SwiftCalcs.active_worksheet.settings.derived_units = derived;
				setUnitSidebar(SwiftCalcs.active_worksheet);
				break;
		}
		showApplyNow();
	}
	_.loadSettingsPane = function() {
		window.showPopupOnTop();
		$('.popup_dialog .full').html(settingsHTML);
    $('.popup_dialog .bottom_links').html('<button class="submit" style="display:none;">Save Settings and Recalculate</button><button class="close grey">Close</button>');
    window.resizePopup(false);
		$('select.angle_mode').val(this.settings.angle).on('change', handleSelectChange);
		$('select.complex_mode').val(this.settings.complex).on('change', handleSelectChange);
		$('select.unit_mode').val(this.settings.units).on('change', handleSelectChange);
		$('select.digits_select').val(this.settings.digits).on('change', handleSelectChange);
		$('.popup_dialog .bottom_links button.close').on('click', function(e) {
			$('.popup_dialog .settings').remove();
			window.hideDialogs();
		});
		$('.popup_dialog .bottom_links button.submit').on('click', function(_this) { return function(e) {
			$('.popup_dialog .settings').remove();
			window.hideDialogs();
			_this.jQ.closest('.active_holder').find('td.settings .message').html(_this.setSettingsText())
			_this.settingsToGiac(true);
		}; }(this));
		setUnitSidebar(this);
		var _this = this;
		$('').html('Add a Unit').on('click', function(e) {
			_this.settings.derived_units.push('');
			setUnitSidebar(_this);
			$('span.custom_unit_box').last().click();
		}).appendTo('div.custom_units .add_unit');
		$('').html('Remove all Derived Units').on('click', function(e) {
			_this.settings.derived_units = [];
			setUnitSidebar(_this);
		}).appendTo('div.custom_units .remove_units');
	}
	_.bindSettings = function() {
		if(!(this.settings.saved == "true") && !(this.settings.saved ===true))
			this.settings = default_settings;
		// Add new settings that aren't in all files
		if(typeof this.settings.digits === 'undefined') this.settings.digits = default_settings.digits;
		this.settingsToGiac(false);
		return this;
	}
	_.unbindSettings = function() {
		return this;
	}
	_.settingsToGiac = function(recalculate) {
		giac.sendCommand({restart_string: "DIGITS:=" + (this.settings.digits) + ";complex_mode:=" + (this.settings.complex == 'on' ? '1' : '0') + ";angle_radian:=" + (this.settings.angle == 'rad' ? '1' : '0') + ";set_units(_" + (this.settings.angle == 'rad' ? 'rad' : 'deg') + ");", set_units: this.settings.base_units.concat(this.settings.derived_units)});
		if(recalculate !== false) {
			this.settings.saved = true;
			if(this.rights >= 3) window.silentRequest('/worksheet_commands', {command: 'update_settings', data: {id: this.server_id, settings: this.settings } });
			$('.apply_now').removeClass('shown').hide();
			SwiftCalcs.active_worksheet.ends[-1].evaluate(true, true); if(!SwiftCalcs.giac.auto_evaluation) { SwiftCalcs.giac.manualEvaluation(); }
		}
	}
});
<commit_msg>Fix settings text not getting updated<commit_after>/************************************************************************
 * Set settings using the settings sidebar.  Also sets settings on bind *
 ************************************************************************/

Worksheet.open(function(_) {
	var default_settings = { angle: 'rad', complex: 'on', units: 'mks', digits: '9', custom_units: false, base_units: ['m','kg','s','K'], derived_units: ['A','mol','cd','E','N','Ohm','Pa','J','T','C','F','H','Hz','V','W','Wb'] };
	var showApplyNow = function() {
		$('.popup_dialog .bottom_links button.submit').show();
	}
	_.setSettingsText = function() {
		var out = "";
		out += this.settings.angle == 'rad' ? 'Rad' : 'Deg';
		out += ", ";
		out += this.settings.complex == 'on' ? 'Complex' : 'Real';
		out += ", ";
		out += this.settings.digits;
		out += " digits, " + this.settings.base_units[0] + ', ' + this.settings.base_units[1] + ', ' + this.settings.base_units[2] + ', ' + this.settings.base_units[3];
		return out;
	}
	var settingsHTML = "
"
			+ "
 Worksheet Settings
"
			+ "
"
			+ "Angle Mode: "
			+ "
<select class='angle_mode' data-type='angle_mode'>"
			+ "<option value='rad'>Radians</option>"
			+ "<option value='deg'>Degrees</option>"
			+ "</select>
"
			+ "
"
			+ "
"
			+ "Complex Mode: "
			+ "
<select class='complex_mode' data-type='complex_mode'>"
			+ "<option value='on'>Enabled</option>"
			+ "<option value='off'>Disabled</option>"
			+ "</select>
"
			+ "
"
			+ "
"
			+ "Significant Digits: "
			+ "
<select class='digits_select' data-type='digits_select'>"
			+ "<option value='1'>1</option>"
			+ "<option value='2'>2</option>"
			+ "<option value='3'>3</option>"
			+ "<option value='4'>4</option>"
			+ "<option value='5'>5</option>"
			+ "<option value='6'>6</option>"
			+ "<option value='7'>7</option>"
			+ "<option value='8'>8</option>"
			+ "<option value='9'>9</option>"
			+ "<option value='10'>10</option>"
			+ "<option value='11'>11</option>"
			+ "<option value='12'>12</option>"
			+ "<option value='13'>13</option>"
			+ "<option value='14'>14</option>"
			+ "</select>
"
			+ "
"
			+ "
"
			+ "Unit System: "
			+ "
<select class='unit_mode' data-type='unit_mode'>"
			+ "<option value='mks'>Meters-Kilograms-Seconds</option>"
			+ "<option value='cgs'>Centimeter-Grams-Seconds</option>"
			+ "<option value='ips'>Inch-Pounds-Seconds</option>"
			+ "</select>"
			+ "
customize
"
			+ "
"
			+ "
"
			+ "
Base Units
"
			+ "

"
			+ "
Length:
"
			+ "
Mass:
"
			+ "
Time:
"
			+ "
Temperature:
"
			+ "

"
			+ "
Derived Units
"
			+ "
"
			+ "Derived units are combinations of base units.  For example, force is mass * length / time^2, but we often express in its own unit for simplicity.  Add derived units to the list below.  When found in answer, base units will be auto-simplified to the derived equivalent."
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
"
			+ "
";
	var setUnitSidebar = function(_this) {
		if((_this.settings.custom_units == "true") || (_this.settings.custom_units ===true)) {
	    $('div.custom_units').addClass('shown');
	    $('a.custom_units').hide();
		} else {
	    $('a.custom_units').show();
	    $('div.custom_units').removeClass('shown');
		}
		$('div.custom_units span.length').html('' + _this.latexToHtml("\\Unit{" + _this.settings.base_units[0] + "}") + '');
		$('div.custom_units span.mass').html('' + _this.latexToHtml("\\Unit{" + _this.settings.base_units[1] + "}") + '');
		$('div.custom_units span.time').html('' + _this.latexToHtml("\\Unit{" + _this.settings.base_units[2] + "}") + '');
		$('div.custom_units span.temp').html('' + _this.latexToHtml("\\Unit{" + _this.settings.base_units[3] + "}") + '');
		$('div.custom_units .added_units').html('');
		for(var i = 0; i < _this.settings.derived_units.length; i++) {
			$('
').addClass('derived_unit').html('' + _this.latexToHtml("\\Unit{" + _this.settings.derived_units[i] + "}") + '').appendTo($('div.custom_units .added_units'));
		}
		$('div.custom_units .added_units i.fa-times').on('click', function(e) {
			$(this).closest('.derived_unit').remove();
			_this.buildUnitSettings();
			e.preventDefault();
			e.stopPropagation();
			return false;
		})
		var mq_onblur = function(_this) {
			return function(mq) {
				$('span.standalone_textarea').remove();
				var jQ = mq.jQ;
				var unit = mq.latex();
				var unit_text = mq.text().replace(/_/g,'');
				if(!unit_text.match(/^[a-z2µ]+$/i)) {
					showNotice('Unit settings should only be single units (m, N, Pa, etc), not combined units (m/s).', 'red');
					unit_text = unit.replace(/^\\Unit\{(.*)\}$/,"$1");
				} else {
					showApplyNow();
				}
				mq.revert();
				jQ.html('');
				var span = $('').addClass('custom_unit_box');
				span.attr('data-unit', unit_text);
				jQ.append(span);
				_this.buildUnitSettings();
			}
		}
		$('span.custom_unit_box').on('click', function(e) {
			var span = $('').addClass('choose_unit').appendTo($(this).parent());
			var mq = window.standaloneMathquill(span, false, true, { blur: mq_onblur(_this) });
			mq.setUnitsOnly(true);
			mq.write("\\Unit{" + $(this).attr('data-unit') + "}");
			//mq.focus();
			mq.keystroke("Left", {preventDefault: function() {} });
			$(this).remove();
		});
	}
	_.buildUnitSettings = function() {
		this.settings.base_units[0] = $('div.custom_units span.length .custom_unit_box').attr('data-unit');
		this.settings.base_units[1] = $('div.custom_units span.mass .custom_unit_box').attr('data-unit');
		this.settings.base_units[2] = $('div.custom_units span.time .custom_unit_box').attr('data-unit');
		this.settings.base_units[3] = $('div.custom_units span.temp .custom_unit_box').attr('data-unit');
		this.settings.derived_units = [];
		var _this = this;
		$('div.custom_units .added_units .custom_unit_box').each(function() {
			_this.settings.derived_units.push($(this).attr('data-unit'));
		});
		this.settings.custom_units = $('div.custom_units').hasClass('shown');
		setUnitSidebar(this);
	}
	var handleSelectChange = function(e) {
		switch($(this).attr('data-type')) {
			case 'angle_mode':
				SwiftCalcs.active_worksheet.settings.angle = $(this).val();
				break;
			case 'complex_mode':
				SwiftCalcs.active_worksheet.settings.complex = $(this).val();
				break;
			case 'digits_select':
				SwiftCalcs.active_worksheet.settings.digits = $(this).val();
				break;
			case 'unit_mode':
				SwiftCalcs.active_worksheet.settings.units = $(this).val();
				switch(SwiftCalcs.active_worksheet.settings.units) {
					case 'mks':
						var base = ['m','kg','s','K'];
						var derived = ['A','mol','cd','E','N','Ohm','Pa','J','T','C','F','H','Hz','V','W','Wb'];
						break;
					case 'cgs':
						var base = ['cm','g','s','K'];
						var derived = ['mL','A','mol','cd','E','N','Ohm','Pa','J','T','C','F','H','Hz','V','W','Wb'];
						break;
					case 'ips':
						var base = ['in','lb','s','Rankine'];
						var derived = ['gal','A','mol','cd','E','lbf','Ohm','psi','Btu','T','C','F','H','Hz','V','hp','Wb'];
						break;
				}
				SwiftCalcs.active_worksheet.settings.base_units = base;
				SwiftCalcs.active_worksheet.settings.derived_units = derived;
				setUnitSidebar(SwiftCalcs.active_worksheet);
				break;
		}
		showApplyNow();
	}
	_.loadSettingsPane = function() {
		window.showPopupOnTop();
		$('.popup_dialog .full').html(settingsHTML);
    $('.popup_dialog .bottom_links').html('<button class="submit" style="display:none;">Save Settings and Recalculate</button><button class="close grey">Close</button>');
    window.resizePopup(false);
		$('select.angle_mode').val(this.settings.angle).on('change', handleSelectChange);
		$('select.complex_mode').val(this.settings.complex).on('change', handleSelectChange);
		$('select.unit_mode').val(this.settings.units).on('change', handleSelectChange);
		$('select.digits_select').val(this.settings.digits).on('change', handleSelectChange);
		$('.popup_dialog .bottom_links button.close').on('click', function(e) {
			$('.popup_dialog .settings').remove();
			window.hideDialogs();
		});
		$('.popup_dialog .bottom_links button.submit').on('click', function(_this) { return function(e) {
			$('.popup_dialog .settings').remove();
			window.hideDialogs();
			_this.jQ.closest('.active_holder').find('div.settings').html(_this.setSettingsText())
			_this.settingsToGiac(true);
		}; }(this));
		setUnitSidebar(this);
		var _this = this;
		$('').html('Add a Unit').on('click', function(e) {
			_this.settings.derived_units.push('');
			setUnitSidebar(_this);
			$('span.custom_unit_box').last().click();
		}).appendTo('div.custom_units .add_unit');
		$('').html('Remove all Derived Units').on('click', function(e) {
			_this.settings.derived_units = [];
			setUnitSidebar(_this);
		}).appendTo('div.custom_units .remove_units');
	}
	_.bindSettings = function() {
		if(!(this.settings.saved == "true") && !(this.settings.saved ===true))
			this.settings = default_settings;
		// Add new settings that aren't in all files
		if(typeof this.settings.digits === 'undefined') this.settings.digits = default_settings.digits;
		this.settingsToGiac(false);
		return this;
	}
	_.unbindSettings = function() {
		return this;
	}
	_.settingsToGiac = function(recalculate) {
		giac.sendCommand({restart_string: "DIGITS:=" + (this.settings.digits) + ";complex_mode:=" + (this.settings.complex == 'on' ? '1' : '0') + ";angle_radian:=" + (this.settings.angle == 'rad' ? '1' : '0') + ";set_units(_" + (this.settings.angle == 'rad' ? 'rad' : 'deg') + ");", set_units: this.settings.base_units.concat(this.settings.derived_units)});
		if(recalculate !== false) {
			this.settings.saved = true;
			if(this.rights >= 3) window.silentRequest('/worksheet_commands', {command: 'update_settings', data: {id: this.server_id, settings: this.settings } });
			$('.apply_now').removeClass('shown').hide();
			SwiftCalcs.active_worksheet.ends[-1].evaluate(true, true); if(!SwiftCalcs.giac.auto_evaluation) { SwiftCalcs.giac.manualEvaluation(); }
		}
	}
});
<|endoftext|>


<commit_before>/**
  @module ember-data
*/

import RESTAdapter from "ember-data/adapters/rest-adapter";

/**
  @class JSONAPIAdapter
  @constructor
  @namespace DS
  @extends DS.RESTAdapter
*/
export default RESTAdapter.extend({
  defaultSerializer: '-json-api',

  /**
    @method ajaxOptions
    @private
    @param {String} url
    @param {String} type The request type GET, POST, PUT, DELETE etc.
    @param {Object} options
    @return {Object}
  */
  ajaxOptions: function(url, type, options) {
    let hash = this._super(...arguments);

    if (hash.contentType) {
      hash.contentType = 'application/vnd.api+json';
    }

    let beforeSend = hash.beforeSend;
    hash.beforeSend = function(xhr) {
      xhr.setRequestHeader('Accept', 'application/vnd.api+json');
      if (beforeSend) {
        beforeSend(xhr);
      }
    };

    return hash;
  },

  /**
    @method findMany
    @param {DS.Store} store
    @param {DS.Model} type
    @param {Array} ids
    @param {Array} snapshots
    @return {Promise} promise
  */
  findMany: function(store, type, ids, snapshots) {
    var url = this.buildURL(type.modelName, ids, snapshots, 'findMany');
    return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } });
  },

  /**
    @method pathForType
    @param {String} modelName
    @return {String} path
  **/
  pathForType: function(modelName) {
    var dasherized = Ember.String.dasherize(modelName);
    return Ember.String.pluralize(dasherized);
  },

  // TODO: Remove this once we have a better way to override HTTP verbs.
  /**
    @method updateRecord
    @param {DS.Store} store
    @param {DS.Model} type
    @param {DS.Snapshot} snapshot
    @return {Promise} promise
  */
  updateRecord: function(store, type, snapshot) {
    var data = {};
    var serializer = store.serializerFor(type.modelName);

    serializer.serializeIntoHash(data, type, snapshot, { includeId: true });

    var id = snapshot.id;
    var url = this.buildURL(type.modelName, id, snapshot, 'updateRecord');

    return this.ajax(url, 'PATCH', { data: data });
  }
});
<commit_msg>update coalesceFindRequests doc for JSONAPIAdapter<commit_after>/**
  @module ember-data
*/

import RESTAdapter from "ember-data/adapters/rest-adapter";

/**
  @class JSONAPIAdapter
  @constructor
  @namespace DS
  @extends DS.RESTAdapter
*/
export default RESTAdapter.extend({
  defaultSerializer: '-json-api',

  /**
    @method ajaxOptions
    @private
    @param {String} url
    @param {String} type The request type GET, POST, PUT, DELETE etc.
    @param {Object} options
    @return {Object}
  */
  ajaxOptions: function(url, type, options) {
    let hash = this._super(...arguments);

    if (hash.contentType) {
      hash.contentType = 'application/vnd.api+json';
    }

    let beforeSend = hash.beforeSend;
    hash.beforeSend = function(xhr) {
      xhr.setRequestHeader('Accept', 'application/vnd.api+json');
      if (beforeSend) {
        beforeSend(xhr);
      }
    };

    return hash;
  },

  /**
    By default the JSONAPIAdapter will send each find request coming from a `store.find`
    or from accessing a relationship separately to the server. If your server supports passing
    ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests
    within a single runloop.

    For example, if you have an initial payload of:

    ```javascript
    {
      post: {
        id: 1,
        comments: [1, 2]
      }
    }
    ```

    By default calling `post.get('comments')` will trigger the following requests(assuming the
    comments haven't been loaded before):

    ```
    GET /comments/1
    GET /comments/2
    ```

    If you set coalesceFindRequests to `true` it will instead trigger the following request:

    ```
    GET /comments?filter[id]=1,2
    ```

    Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo`
    relationships accessed within the same runloop. If you set `coalesceFindRequests: true`

    ```javascript
    store.findRecord('comment', 1);
    store.findRecord('comment', 2);
    ```

    will also send a request to: `GET /comments?filter[id]=1,2`

    Note: Requests coalescing rely on URL building strategy. So if you override `buildURL` in your app
    `groupRecordsForFindMany` more likely should be overridden as well in order for coalescing to work.

    @property coalesceFindRequests
    @type {boolean}
  */
  coalesceFindRequests: false,

  /**
    @method findMany
    @param {DS.Store} store
    @param {DS.Model} type
    @param {Array} ids
    @param {Array} snapshots
    @return {Promise} promise
  */
  findMany: function(store, type, ids, snapshots) {
    var url = this.buildURL(type.modelName, ids, snapshots, 'findMany');
    return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } });
  },

  /**
    @method pathForType
    @param {String} modelName
    @return {String} path
  **/
  pathForType: function(modelName) {
    var dasherized = Ember.String.dasherize(modelName);
    return Ember.String.pluralize(dasherized);
  },

  // TODO: Remove this once we have a better way to override HTTP verbs.
  /**
    @method updateRecord
    @param {DS.Store} store
    @param {DS.Model} type
    @param {DS.Snapshot} snapshot
    @return {Promise} promise
  */
  updateRecord: function(store, type, snapshot) {
    var data = {};
    var serializer = store.serializerFor(type.modelName);

    serializer.serializeIntoHash(data, type, snapshot, { includeId: true });

    var id = snapshot.id;
    var url = this.buildURL(type.modelName, id, snapshot, 'updateRecord');

    return this.ajax(url, 'PATCH', { data: data });
  }
});
<|endoftext|>


<commit_before>import { noop } from './noop'

export const warning = process.env.NODE_ENV === 'production'
  ? /* istanbul ignore next */ noop
  : function warning(checker, complainer) {
    if (!checker()) {
      const message = [ '[Vue-Treeselect Warning]' ].concat(complainer())
      // eslint-disable-next-line no-console
      console.error(...message)
      // eslint-disable-next-line no-debugger
      debugger
    }
  }
<commit_msg>remove debugger (#157)<commit_after>import { noop } from './noop'

export const warning = process.env.NODE_ENV === 'production'
  ? /* istanbul ignore next */ noop
  : function warning(checker, complainer) {
    if (!checker()) {
      const message = [ '[Vue-Treeselect Warning]' ].concat(complainer())
      // eslint-disable-next-line no-console
      console.error(...message)
    }
  }
<|endoftext|>


<commit_before>module.exports = {
  env: {
    'browser': true,
    'commonjs': true,
    'node': true,
  },
  extends: 'eslint:recommended',
  rules: {
  	'comma-dangle': 'off',
    'no-console': 'off',
    'no-constant-condition': 'off',
    'no-redeclare': 'off',
    'no-unused-vars': 'off',

    'array-bracket-spacing': 'error',
    'block-spacing': 'error',
    'brace-style': 'error',
    'comma-spacing': 'error',
    'comma-style': 'error',
    'indent': ['error', 2],
  },
};
<commit_msg>ESLint: Enable "eol-last" rule<commit_after>module.exports = {
  env: {
    'browser': true,
    'commonjs': true,
    'node': true,
  },
  extends: 'eslint:recommended',
  rules: {
  	'comma-dangle': 'off',
    'no-console': 'off',
    'no-constant-condition': 'off',
    'no-redeclare': 'off',
    'no-unused-vars': 'off',

    'array-bracket-spacing': 'error',
    'block-spacing': 'error',
    'brace-style': 'error',
    'comma-spacing': 'error',
    'comma-style': 'error',
    'eol-last': 'error',
    'indent': ['error', 2],
  },
};
<|endoftext|>


<commit_before>'use strict'

/**
 * Test dependencies
 */
const chai = require('chai')
const fs = require('fs')
const path = require('path')
const { JWT } = require('@trust/jose')

/**
 * Assertions
 */
chai.use(require('dirty-chai'))
chai.use(require('chai-as-promised'))
chai.should()
let expect = chai.expect

/**
 * Code under test
 */
const Provider = require('../src/Provider')
const IDToken = require('../src/IDToken')
const IDTokenSchema = require('../src/schemas/IDTokenSchema')

/**
 * Tests
 */
describe('IDToken', () => {
  const providerUri = 'https://example.com'
  var provider

  before(function () {
    this.timeout(5000)

    let configPath = path.join(__dirname, 'config', 'provider.json')

    let storedConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'))

    provider = new Provider(storedConfig)

    return provider.initializeKeyChain(provider.keys)
  })

  /**
   * Schema
   */
  describe('schema', () => {
    it('should reference the IDToken Schema', () => {
      IDToken.schema.should.equal(IDTokenSchema)
    })
  })

  describe('issueForRequest()', () => {
    let code
    let subject = { _id: 'user123' }
    let client
    let request, response
    let params

    describe('authentication request', () => {
      beforeEach(() => {
        client = { 'client_id': 'client123' }
        params = { nonce: 'nonce123' }
        request = { params, code, provider, client, subject }
        response = {}
      })

      it('should issue an id token', () => {
        return IDToken.issueForRequest(request, response)
          .then(res => {
            return JWT.decode(res['id_token'])
          })
          .then(token => {
            expect(token.type).to.equal('JWS')
            expect(token.header.alg).to.equal('RS256')
            expect(token.payload.iss).to.equal(providerUri)
            expect(token.payload.sub).to.equal('user123')
            expect(token.payload.aud).to.equal('client123')
            expect(token.payload.azp).to.equal('client123')
          })
      })
    })

    describe('auth code / token request', () => {
      beforeEach(() => {
        params = {}
        code = {
          aud: 'client123',
          sub: 'user123',
          nonce: 'nonce123'
        }
        request = { params, code, provider, client, subject }
        response = {
          code: 'c0de',
          access_token: 't0ken'
        }
      })

      it('should issue an id token', () => {
        return IDToken.issueForRequest(request, response)
          .then(res => {
            return JWT.decode(res['id_token'])
          })
          .then(token => {
            expect(token.type).to.equal('JWS')
            expect(token.header.alg).to.equal('RS256')
            expect(token.payload.iss).to.equal(providerUri)
            expect(token.payload.sub).to.equal('user123')
            expect(token.payload.aud).to.equal('client123')
            expect(token.payload.azp).to.equal('client123')
            expect(token.payload.nonce).to.equal('nonce123')
            expect(token.payload.at_hash).to.equal('tGwJZ3NDJh8LQ5pHJCIiXg')
            expect(token.payload.c_hash).to.equal('OAO0dgmipGQFRlmxSgzfug')
          })
      })
    })
  })

  describe('issue()', () => {
    let options

    beforeEach(() => {
      options = {
        aud: 'client123',
        azp: 'client123',
        sub: 'user123',
        nonce: 'n0nce',
        at_hash: 'athash123',
        c_hash: 'chash123'
      }
    })

    it('should issue an id token', () => {
      let token = IDToken.issue(provider, options)

      expect(token.payload.iss).to.equal(provider.issuer)
      expect(token.payload.aud).to.equal('client123')
      expect(token.payload.azp).to.equal('client123')
      expect(token.payload.sub).to.equal('user123')
      expect(token.payload.nonce).to.equal(options.nonce)
      expect(token.payload.at_hash).to.equal(options.at_hash)
      expect(token.payload.c_hash).to.equal(options.c_hash)
    })

    it('should issue an id token with passed in values', () => {
      options.alg = 'RS512'

      let randomId = IDToken.random(8)
      options.jti = randomId

      let now = Math.floor(Date.now() / 1000)
      options.iat = now

      options.max = 3000

      let token = IDToken.issue(provider, options)

      expect(token.payload.jti).to.equal(randomId)
      expect(token.payload.iat).to.equal(now)
      expect(token.payload.exp - token.payload.iat).to.equal(3000)

      expect(token.header.alg).to.equal('RS512')
    })

    it('should init with defaults', () => {
      let token = IDToken.issue(provider, options)

      expect(token.header.alg).to.equal(IDToken.DEFAULT_SIG_ALGORITHM)
      expect(token.header.kid).to.exist()

      expect(token.payload.jti).to.exist()
      expect(token.payload.exp).to.exist()
      expect(token.payload.iat).to.exist()

      expect(token.payload.exp - token.payload.iat)
        .to.equal(IDToken.DEFAULT_MAX_AGE)

      expect(token.key).to.exist()
    })
  })
})
<commit_msg>test(IDToken): Add support for cnf key claim<commit_after>'use strict'

/**
 * Test dependencies
 */
const chai = require('chai')
const fs = require('fs')
const path = require('path')
const { JWT } = require('@trust/jose')

/**
 * Assertions
 */
chai.use(require('dirty-chai'))
chai.use(require('chai-as-promised'))
chai.should()
let expect = chai.expect

/**
 * Code under test
 */
const Provider = require('../src/Provider')
const IDToken = require('../src/IDToken')
const IDTokenSchema = require('../src/schemas/IDTokenSchema')

/**
 * Tests
 */
describe('IDToken', () => {
  const providerUri = 'https://example.com'
  var provider

  before(function () {
    this.timeout(5000)

    let configPath = path.join(__dirname, 'config', 'provider.json')

    let storedConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'))

    provider = new Provider(storedConfig)

    return provider.initializeKeyChain(provider.keys)
  })

  /**
   * Schema
   */
  describe('schema', () => {
    it('should reference the IDToken Schema', () => {
      IDToken.schema.should.equal(IDTokenSchema)
    })
  })

  describe('issueForRequest()', () => {
    let code
    let subject = { _id: 'user123' }
    let client
    let request, response
    let params, cnfKey

    describe('authentication request', () => {
      beforeEach(() => {
        client = { 'client_id': 'client123' }
        params = { nonce: 'nonce123' }
        cnfKey = {}
        request = { params, code, provider, client, subject, cnfKey }
        response = {}
      })

      it('should issue an id token', () => {
        return IDToken.issueForRequest(request, response)
          .then(res => {
            return JWT.decode(res['id_token'])
          })
          .then(token => {
            expect(token.type).to.equal('JWS')
            expect(token.header.alg).to.equal('RS256')
            expect(token.payload.iss).to.equal(providerUri)
            expect(token.payload.sub).to.equal('user123')
            expect(token.payload.aud).to.equal('client123')
            expect(token.payload.azp).to.equal('client123')
            expect(token.payload.cnf).to.eql({ jwk: cnfKey })
          })
      })
    })

    describe('auth code / token request', () => {
      beforeEach(() => {
        params = {}
        code = {
          aud: 'client123',
          sub: 'user123',
          nonce: 'nonce123'
        }
        cnfKey = {}
        request = { params, code, provider, client, subject, cnfKey }
        response = {
          code: 'c0de',
          access_token: 't0ken'
        }
      })

      it('should issue an id token', () => {
        return IDToken.issueForRequest(request, response)
          .then(res => {
            return JWT.decode(res['id_token'])
          })
          .then(token => {
            expect(token.type).to.equal('JWS')
            expect(token.header.alg).to.equal('RS256')
            expect(token.payload.iss).to.equal(providerUri)
            expect(token.payload.sub).to.equal('user123')
            expect(token.payload.aud).to.equal('client123')
            expect(token.payload.azp).to.equal('client123')
            expect(token.payload.nonce).to.equal('nonce123')
            expect(token.payload.at_hash).to.equal('tGwJZ3NDJh8LQ5pHJCIiXg')
            expect(token.payload.c_hash).to.equal('OAO0dgmipGQFRlmxSgzfug')
            expect(token.payload.cnf).to.eql({ jwk: cnfKey })
          })
      })
    })
  })

  describe('issue()', () => {
    let options

    beforeEach(() => {
      options = {
        aud: 'client123',
        azp: 'client123',
        sub: 'user123',
        nonce: 'n0nce',
        at_hash: 'athash123',
        c_hash: 'chash123',
        cnf: { jwk: {} }
      }
    })

    it('should issue an id token', () => {
      let token = IDToken.issue(provider, options)

      expect(token.payload.iss).to.equal(provider.issuer)
      expect(token.payload.aud).to.equal('client123')
      expect(token.payload.azp).to.equal('client123')
      expect(token.payload.sub).to.equal('user123')
      expect(token.payload.nonce).to.equal(options.nonce)
      expect(token.payload.at_hash).to.equal(options.at_hash)
      expect(token.payload.c_hash).to.equal(options.c_hash)
      expect(token.payload.cnf).to.eql(options.cnf)
    })

    it('should issue an id token with passed in values', () => {
      options.alg = 'RS512'

      let randomId = IDToken.random(8)
      options.jti = randomId

      let now = Math.floor(Date.now() / 1000)
      options.iat = now

      options.max = 3000

      let token = IDToken.issue(provider, options)

      expect(token.payload.jti).to.equal(randomId)
      expect(token.payload.iat).to.equal(now)
      expect(token.payload.exp - token.payload.iat).to.equal(3000)

      expect(token.header.alg).to.equal('RS512')
    })

    it('should init with defaults', () => {
      let token = IDToken.issue(provider, options)

      expect(token.header.alg).to.equal(IDToken.DEFAULT_SIG_ALGORITHM)
      expect(token.header.kid).to.exist()

      expect(token.payload.jti).to.exist()
      expect(token.payload.exp).to.exist()
      expect(token.payload.iat).to.exist()

      expect(token.payload.exp - token.payload.iat)
        .to.equal(IDToken.DEFAULT_MAX_AGE)

      expect(token.key).to.exist()
    })
  })
})
<|endoftext|>


<commit_before>module.exports = {
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true,
        "mocha": true,
        "node": true
    },
    "extends": [
        "eslint:recommended"
        // "plugin:mocha/recommended"
    ],
    "parserOptions": {
        "sourceType": "module"
    },
    "plugins": [
        "chai-expect",
        "html",
        "mocha"
    ],
    "rules": {
        "array-bracket-spacing"      : ["error", "never"],
        "array-callback-return"      : ["error"],
        "block-scoped-var"           : ["error"],
        "block-spacing"              : ["error", "always"],
        "curly"                      : ["error"],
        "dot-notation"               : ["error"],
        "eqeqeq"                     : ["error"],
        "indent"                     : ["error", 4],
        "linebreak-style"            : ["error", "unix"],
        "no-console"                 : ["warn"],
        "no-floating-decimal"        : ["error"],
        "no-implicit-coercion"       : ["error"],
        "no-implicit-globals"        : ["error"],
        "no-loop-func"               : ["error"],
        "no-return-assign"           : ["error"],
        "no-template-curly-in-string": ["error"],
        "no-unneeded-ternary"        : ["error"],
        "no-unused-vars"             : ["error", { "args": "none" }],
        "no-useless-computed-key"    : ["error"],
        "no-useless-return"          : ["error"],
        "no-var"                     : ["error"],
        "prefer-const"               : ["error"],
        "quotes"                     : ["error", "single"],
        "semi"                       : ["error", "always"],

        "mocha/no-exclusive-tests"   : ["warn"],
        "mocha/no-global-tests"      : ["error"],
        "mocha/no-identical-title"   : ["error"],
        "mocha/no-mocha-arrows"      : ["error"]
    }
};
<commit_msg>Update ESLint to recommended settings<commit_after>module.exports = {
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true,
        "mocha": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:mocha/recommended"
    ],
    "parserOptions": {
        "sourceType": "module"
    },
    "plugins": [
        "chai-expect",
        "html",
        "mocha"
    ],
    "rules": {
        "array-bracket-spacing"      : ["error", "never"],
        "array-callback-return"      : ["error"],
        "block-scoped-var"           : ["error"],
        "block-spacing"              : ["error", "always"],
        "curly"                      : ["error"],
        "dot-notation"               : ["error"],
        "eqeqeq"                     : ["error"],
        "indent"                     : ["error", 4],
        "linebreak-style"            : ["error", "unix"],
        "no-console"                 : ["warn"],
        "no-floating-decimal"        : ["error"],
        "no-implicit-coercion"       : ["error"],
        "no-implicit-globals"        : ["error"],
        "no-loop-func"               : ["error"],
        "no-return-assign"           : ["error"],
        "no-template-curly-in-string": ["error"],
        "no-unneeded-ternary"        : ["error"],
        "no-unused-vars"             : ["error", { "args": "none" }],
        "no-useless-computed-key"    : ["error"],
        "no-useless-return"          : ["error"],
        "no-var"                     : ["error"],
        "prefer-const"               : ["error"],
        "quotes"                     : ["error", "single"],
        "semi"                       : ["error", "always"],

        "mocha/no-hooks-for-single-case": ["off"],
        "mocha/no-top-level-hooks"      : ["off"],
        "mocha/no-setup-in-describe"    : ["off"]
    }
};
<|endoftext|>


<commit_before>module.exports = {
	env: {
		"es6": true,
		// "es2020": true,
		"node": true,
		"browser": true,
		"shared-node-browser": true,
		"mocha": true,
		"jest": true,
		"mongo": true,
	},
	extends: "eslint:recommended",
	parserOptions: {
		ecmaVersion: 11,
		sourceType: "module",
	},
	parser: "babel-eslint",
	rules: {
		"indent": [
			"error",
			"tab",
			{
				VariableDeclarator: "first",
			},
		],
		"linebreak-style": ["error", "unix"],
		"curly": "error",
		"quotes": [
			"warn",
			"single",
			{
				avoidEscape: true,
				allowTemplateLiterals: true,
			},
		],
		"semi": ["error", "always"],
		"no-console": [
			"warn",
			{
				allow: ["warn", "error", "info"],
			},
		],
		"brace-style": [
			"error",
			"1tbs",
			{
				allowSingleLine: true,
			},
		],
		"no-unused-vars": [
			"warn",
			{
				vars: "all",
				args: "after-used",
				ignoreRestSiblings: false,
			},
		],
		"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
		"no-trailing-spaces": "error",
		"arrow-parens": ["error", "always"],
		"arrow-body-style": ["warn", "always"],
		"func-style": [
			"warn",
			"declaration",
			{
				allowArrowFunctions: true,
			},
		],
		"no-confusing-arrow": [
			"error",
			{
				allowParens: false,
			},
		],
		"arrow-spacing": "error",
		"prefer-arrow-callback": "warn",
		"require-await": "error",
		"operator-linebreak": ["warn", "before"],
	},
};
<commit_msg>update .eslintrc<commit_after>module.exports = {
	env: {
		"es6": true,
		// "es2020": true,
		"node": true,
		"browser": true,
		"shared-node-browser": true,
		"mocha": true,
		"jest": true,
		"mongo": true,
	},
	extends: "eslint:recommended",
	parserOptions: {
		ecmaVersion: 11,
		sourceType: "module",
	},
	parser: "babel-eslint",
	rules: {
		"indent": [
			"error",
			"tab",
			{
				VariableDeclarator: "first",
			},
		],
		"linebreak-style": ["error", "unix"],
		"curly": "error",
		"quotes": [
			"warn",
			"single",
			{
				avoidEscape: true,
				allowTemplateLiterals: true,
			},
		],
		"semi": ["error", "always"],
		"no-console": [
			"warn",
			{
				allow: ["warn", "error", "info"],
			},
		],
		"brace-style": [
			"error",
			"1tbs",
			{
				allowSingleLine: true,
			},
		],
		"no-unused-vars": [
			"warn",
			{
				vars: "all",
				args: "after-used",
				ignoreRestSiblings: false,
			},
		],
		"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
		"no-trailing-spaces": "error",
		"arrow-parens": ["error", "always"],
		"arrow-body-style": ["warn", "always"],
		"func-style": [
			"warn",
			"declaration",
			{
				allowArrowFunctions: true,
			},
		],
		"no-confusing-arrow": [
			"error",
			{
				allowParens: false,
			},
		],
		"arrow-spacing": "error",
		"prefer-arrow-callback": "warn",
		"require-await": "error",
		"operator-linebreak": ["warn", "before"],
		"no-constant-condition": ["error", { "checkLoops": false }]
	},
};
<|endoftext|>


<commit_before>'use strict'

module.exports = {
  parser: 'babel-eslint',

  extends: [
    '@strv/node/v8',
    '@strv/node/optional',
    '@strv/node/style',
    '@strv/mocha',
  ],

  rules: {
    // If your editor cannot show these to you, occasionally turn this off and run the linter
    'no-warning-comments': 0,

    'node/no-unsupported-features/es-syntax': ['error', {
      ignores: ['modules'],
    }],

    'node/shebang': ['warn', {
      convertPath: {
        '**/*.mjs': ['^(\.+).mjs', '$1.js'],
      },
    }],
  },

  overrides: [{
    files: [
      '**/*.test.mjs',
    ],

    globals: {
      sinon: true,
      expect: true,
    },

    rules: {
      'max-classes-per-file': 'off',
    },
  }],
}
<commit_msg>chore: remove unnecessary escape from eslint config<commit_after>'use strict'

module.exports = {
  parser: 'babel-eslint',

  extends: [
    '@strv/node/v8',
    '@strv/node/optional',
    '@strv/node/style',
    '@strv/mocha',
  ],

  rules: {
    // If your editor cannot show these to you, occasionally turn this off and run the linter
    'no-warning-comments': 0,

    'node/no-unsupported-features/es-syntax': ['error', {
      ignores: ['modules'],
    }],

    'node/shebang': ['warn', {
      convertPath: {
        '**/*.mjs': ['^(.+).mjs', '$1.js'],
      },
    }],
  },

  overrides: [{
    files: [
      '**/*.test.mjs',
    ],

    globals: {
      sinon: true,
      expect: true,
    },

    rules: {
      'max-classes-per-file': 'off',
    },
  }],
}
<|endoftext|>


<commit_before>'use strict';

let cli   = require('heroku-cli-util');
let nock  = require('nock');
let sinon = require('sinon');
let cmd   = require('../../../commands/hello/app');

describe('hello:app', function () {
  beforeEach(function () {
    this.cliDebug = sinon.stub(cli, 'debug');
  });

  afterEach(function () {
    this.cliDebug.restore();
  });
  it('does stuff', function () {
    let self   = this;
    let app    = {name: 'myapp', web_url: 'https://myapp.herokuapp.com/'};
    let config = {};

    nock('https://api.heroku.com')
    .get('/apps/myapp')
    .reply(200, app);

    nock('https://api.heroku.com')
    .get('/apps/myapp/config-vars')
    .reply(200, config);

    return cmd.run({app: 'myapp'})
    .then(function () {
      self.cliDebug.should.have.been.calledWith(app);
      self.cliDebug.should.have.been.calledWith(config);
    });
  });
});
<commit_msg>actually use something in config var test<commit_after>'use strict';

let cli   = require('heroku-cli-util');
let nock  = require('nock');
let sinon = require('sinon');
let cmd   = require('../../../commands/hello/app');

describe('hello:app', function () {
  beforeEach(function () {
    this.cliDebug = sinon.stub(cli, 'debug');
  });

  afterEach(function () {
    this.cliDebug.restore();
  });
  it('does stuff', function () {
    let self   = this;
    let app    = {name: 'myapp', web_url: 'https://myapp.herokuapp.com/'};
    let config = {FOO: 'bar'};

    nock('https://api.heroku.com')
    .get('/apps/myapp')
    .reply(200, app);

    nock('https://api.heroku.com')
    .get('/apps/myapp/config-vars')
    .reply(200, config);

    return cmd.run({app: 'myapp'})
    .then(function () {
      self.cliDebug.should.have.been.calledWith(app);
      self.cliDebug.should.have.been.calledWith(config);
    });
  });
});
<|endoftext|>


<commit_before>const package = require('./package.json')

module.exports = {
  parser: 'babel-eslint',
  env: {
    browser: true,
    commonjs: true,
    es6: true,
    jest: true,
    node: true
  },
  extends: [
    'eslint:recommended',
    'plugin:import/errors',
    'plugin:react/recommended',
    'plugin:flowtype/recommended',

    // suppress conflicted rules
    'plugin:prettier/recommended',
    'prettier/flowtype',
    'prettier/react'
  ],
  parserOptions: {
    ecmaFeatures: {
      experimentalObjectRestSpread: true,
      jsx: true
    },
    sourceType: 'module'
  },
  plugins: ['emotion', 'flowtype'],
  settings: {
    react: {
      version: package.dependencies.react
    }
  },
  rules: {
    'no-console': 'warn',
    'emotion/import-from-emotion': 'error',
    'emotion/jsx-import': 'error',
    'emotion/no-vanilla': 'error',
    'emotion/styled-import': 'error',
    'emotion/syntax-preference': ['error', 'string'],
    'flowtype/require-valid-file-annotation': ['warn', 'always'],
    'react/no-deprecated': 'warn',
    'react/prefer-stateless-function': 'error'
  }
}
<commit_msg>:shower: Remove unnecessary lint settings<commit_after>const package = require('./package.json')

module.exports = {
  parser: 'babel-eslint',
  env: {
    browser: true,
    commonjs: true,
    es6: true,
    jest: true,
    node: true
  },
  extends: [
    'eslint:recommended',
    'plugin:import/errors',
    'plugin:react/recommended',
    'plugin:flowtype/recommended',

    // suppress conflicted rules
    'plugin:prettier/recommended',
    'prettier/flowtype',
    'prettier/react'
  ],
  parserOptions: {
    ecmaFeatures: {
      experimentalObjectRestSpread: true,
      jsx: true
    },
    sourceType: 'module'
  },
  plugins: ['flowtype'],
  settings: {
    react: {
      version: package.dependencies.react
    }
  },
  rules: {
    'no-console': 'warn',
    'flowtype/require-valid-file-annotation': ['warn', 'always'],
    'react/no-deprecated': 'warn',
    'react/prefer-stateless-function': 'error'
  }
}
<|endoftext|>


<commit_before>module.exports = {
    extends: ['airbnb', 'prettier', 'prettier/flowtype', 'prettier/react'],
    env: {
        browser: true,
    },
    plugins: ['prettier', 'flowtype'],
    rules: {
        // `off` to allow defining internal helper functions after the exported objects
        'no-use-before-define': 'off',
        // `warn` in order to avoid defining all props on wrapper components
        'react/prop-types': 'warn',
        // `off` as flow warns about using possibly undefined values
        'react/require-default-props': 'off',
        // allow reassigning a variable in the test of a while or do...while loop
        'no-cond-assign': ['error', 'except-parens'],
        // `warn` to allow unfinished modules that will have multiple exports
        'import/prefer-default-export': 'warn',
        // don't use .jsx extensions
        'react/jsx-filename-extension': ['warn', { extensions: ['.js'] }],
        // render above everything-else, so it can be found more easily
        'react/sort-comp': [
            'warn',
            {
                order: [
                    'type-annotations',
                    'static-methods',
                    'lifecycle',
                    'render',
                    'everything-else',
                ],
            },
        ],
        // flowtype specific warnings
        'flowtype/define-flow-type': 'warn',
        'flowtype/require-parameter-type': 'warn',
        'flowtype/use-flow-type': 'warn',

        // eslint-config-prettier rules that might cause problems
        // see: https://github.com/prettier/eslint-config-prettier#special-rules
        curly: ['error', 'multi-line'],
        'max-len': [
            'error',
            80,
            4,
            {
                ignoreUrls: true,
                ignoreComments: false,
                ignoreRegExpLiterals: true,
                ignoreStrings: true,
                ignoreTemplateLiterals: true,
            },
        ],
        'no-tabs': 'error',

        // eslint-plugin-prettier rules
        'prettier/prettier': [
            'error',
            {
                tabWidth: 4,
                semi: false,
                singleQuote: true,
                trailingComma: 'all',
            },
        ],
    },
    settings: {
        flowtype: {
            onlyFilesWithFlowAnnotation: true,
        },
    },
}
<commit_msg>No trailing commas in lists of function arguments<commit_after>module.exports = {
    extends: ['airbnb', 'prettier', 'prettier/flowtype', 'prettier/react'],
    env: {
        browser: true,
    },
    plugins: ['prettier', 'flowtype'],
    rules: {
        // `off` to allow defining internal helper functions after the exported objects
        'no-use-before-define': 'off',
        // `warn` in order to avoid defining all props on wrapper components
        'react/prop-types': 'warn',
        // `off` as flow warns about using possibly undefined values
        'react/require-default-props': 'off',
        // allow reassigning a variable in the test of a while or do...while loop
        'no-cond-assign': ['error', 'except-parens'],
        // `warn` to allow unfinished modules that will have multiple exports
        'import/prefer-default-export': 'warn',
        // don't use .jsx extensions
        'react/jsx-filename-extension': ['warn', { extensions: ['.js'] }],
        // render above everything-else, so it can be found more easily
        'react/sort-comp': [
            'warn',
            {
                order: [
                    'type-annotations',
                    'static-methods',
                    'lifecycle',
                    'render',
                    'everything-else',
                ],
            },
        ],
        // flowtype specific warnings
        'flowtype/define-flow-type': 'warn',
        'flowtype/require-parameter-type': 'warn',
        'flowtype/use-flow-type': 'warn',

        // eslint-config-prettier rules that might cause problems
        // see: https://github.com/prettier/eslint-config-prettier#special-rules
        curly: ['error', 'multi-line'],
        'max-len': [
            'error',
            80,
            4,
            {
                ignoreUrls: true,
                ignoreComments: false,
                ignoreRegExpLiterals: true,
                ignoreStrings: true,
                ignoreTemplateLiterals: true,
            },
        ],
        'no-tabs': 'error',

        // eslint-plugin-prettier rules
        'prettier/prettier': [
            'error',
            {
                tabWidth: 4,
                semi: false,
                singleQuote: true,
                trailingComma: 'es5',
            },
        ],
    },
    settings: {
        flowtype: {
            onlyFilesWithFlowAnnotation: true,
        },
    },
}
<|endoftext|>


<commit_before>import * as Weights from "../Weights.js";

export { Params, Layer };

/**
 * Embedding (2D) layer parameters.
 */
class Params extends Weights.Params {

  /**
   * @param {number} channelMultiplier
   *   Every input channel will be expanded into so many embedding channels. The outChannels (output channel count)
   * is always depending on channelMultiplier and equal to ( inChannels * channelMultiplier ). If null, it will be
   * extracted from inputFloat32Array (i.e. by evolution).
   *
   * @return {boolean} Return false, if initialization failed.
   *
   * @override
   */
  init( inputFloat32Array, byteOffsetBegin, inChannels, channelMultiplier = null ) {

//!!! ...unfinished...
// inverted residual connection (by add or by concatenate) ? (dense net)
// squeeze-and-excitation ?
// Shuffled Grouped Pointwise Convolution ... ? (by tf.gather() ?)

    let parameterMap = new Map( [
      [ Weights.Params.Keys.inChannels,        inChannels ],
      [ Weights.Params.Keys.channelMultiplier, channelMultiplier ],

      // For an embedding layer, its output channel count always depends on channelMultiplier.
      [ Weights.Params.Keys.outChannels,       Infinity ],
    ] );

    return super.init( inputFloat32Array, byteOffsetBegin, parameterMap );
  }

}

/**
 * An embedding layer contains one params (this.params) and inChannels embedding vocabulary tables.
 * Every input channel has one embedding vocabulary table. Every embedding vocabulary table has
 * vocabularyCountPerInputChannel vocabularies. Every vocabulary has channelMultiplier embedding channels.
 *
 * @member {Array of number} inputScaleToSize
 *   Scale the height and width of the input image to size [ inputScaleToHeight, inputScaleToWidth ]
 * (in pixels) before convoluting. For text input, the inputScaleToHeight should be 1. If null, there will be
 * no scaling when predict().
 *
 * @member {number} vocabularyCountPerInputChannel
 *   Every input channel will have how many vocabularies. This is also vocabulary count per vocabulary table (because
 * every input channel has a vocabulary table). For an image data (R-G-B-A four channels), there will be 256
 * vocabularies per input channel because every channel is represented by one byte (8 bits) which has 2^8 = 256 kinds
 * of possible values.
 *
 * @member {number} embeddingChannelCountPerInputChannel
 *   Every vocabulary will have how many embedding channels. Every input channel will be expanded into so many
 * embedding channels. This is same as the this.params.channelMultiplier.
 */
class Layer {

  /**
   * @param {Float32Array} inputFloat32Array
   *   A Float32Array whose values will be interpret as weights.
   *
   * @param {number} byteOffsetBegin
   *   The position to start to decode from the inputFloat32Array. This is relative to the inputFloat32Array.buffer
   * (not to the inputFloat32Array.byteOffset).
   *
   * @param {number} inChannels
   *   The input channel count.
   *
   * @param {number} channelMultiplier
   *   Every vocabulary will have how many embedding channels. Every input channel will be expanded into so many
   * embedding channels. The outChannels (output channel count) is always depending on channelMultiplier and equal
   * to ( inChannels * channelMultiplier ). If null, it will be extracted from inputFloat32Array (i.e. by evolution).
   *
   * @return {boolean} Return false, if initialization failed.
   */
  init(
    inputFloat32Array, byteOffsetBegin,
    inputScaleToSize, inChannels, vocabularyCountPerInputChannel, channelMultiplier = null ) {

//!!! ...unfinished...
// inverted residual connection (by add or by concatenate) ? (dense net)
// squeeze-and-excitation ?
// Shuffled Grouped Pointwise Convolution ... ? (by tf.gather() ?)

    disposeTensors();
    this.params = this.vocabularyTables = null; // So that distinguishable if re-initialization failed.

    this.inputScaleToSize = inputScaleToSize;
    this.vocabularyCountPerInputChannel = vocabularyCountPerInputChannel;

    this.params = new Params();
    if ( !this.params.init( inputFloat32Array, byteOffsetBegin, inChannels, channelMultiplier ) )
      return false;

    let embeddingChannelCountPerInputChannel = this.embeddingChannelCountPerInputChannel; // The real channelMultiplier.
    let vocabularyTableShape = [ vocabularyCountPerInputChannel, embeddingChannelCountPerInputChannel ];

    // Extract data of vocabulary tables.
    this.vocabularyTables = new Array( inChannels );
    {
      let nextByteOffsetBegin = this.params.defaultByteOffsetEnd;
      for ( let i = 0; i < inChannels; ++i ) {
        this.vocabularyTables[ i ] = new Weights.Base();
        if ( !this.vocabularyTables[ i ].init( inputFloat32Array, nextByteOffsetBegin, null, 0, vocabularyTableShape ) )
          return false;  // e.g. input array do not have enough data.
        nextByteOffsetBegin = this.vocabularyTables[ i ].defaultByteOffsetEnd;
      }
    }

    // Build tf.tensor of vocabulary tables.
    try {
      this.vocabularyTablesTensor2DArray = tf.tidy( "Embedding2D.Layer.buildTensors", () => {
        return this.vocabularyTables.map( ( vocabularyTable, i ) => {
//!!! residual (concat id) in advance ?
          tf.tensor2d( vocabularyTable, vocabularyTableShape )
        });
      });
    } catch ( e ) {
      return false; // e.g. out of (GPU) memory.
    }

    return true;
  }

  isValid() {
    if ( this.vocabularyTablesTensors )
      if ( this.vocabularyTablesTensors[ this.params.inChannels - 1 ] ) // At least, there should be one vocabulary table.
        if ( this.vocabularyTables[ this.params.inChannels - 1 ].isValid() )  // the last vocabulary table is valid.

          this.vocabularyTablesTensors
          return true;
    return false;
  }

  /** Release tf.tensor. */
  disposeTensors() {
    tf.dispose( this.vocabularyTablesTensors );
    this.vocabularyTablesTensors = null;
  }

  /**
   * Process the input and produce output by using the weights of this neural network layer.
   *
   * @param {tf.tensor3D} inputTensor3D
   *   A tensor3D data (e.g. height-width-color for color image, or 1-width-1 for text) with
   * this.inChannels (e.g. 4 for r-g-b-a, or 1 for text) channels.
   *
   * @return {tf.tensor3D} The predicted output as tensor3D. Return null, if failed (e.g. out of GPU memory).
   */
  predict( inputTensor3D ) {
    const predictResult = tf.tidy( "Embedding2D.Layer.predict", () => {
      try {

        // Scale input into specific size.
        let scaledInput;
        if (   ( !this.inputScaleToSize )                                       // No scaling information.
            || (   ( this.inputScaleToSize[ 0 ] == inputTensor3D.shape[ 0 ] )   // Or, already same size.
                && ( this.inputScaleToSize[ 1 ] == inputTensor3D.shape[ 1 ] ) )
           ) {
          scaledInput = inputTensor3D;
        } else {
          // Otherwise, scaling by using ( alignCorners == true ) for better looking when visualizing.
          scaledInput = inputTensor3D.resizeBilinear( inputTensor3D, this.inputScaleToSize, true );
        }

        // For example, suppose input is a color image (i.e. height-width-color tensor3D). The last
        // axis is a 4 color (r-g-b-a) channel. Splitting along the last axis (the color channel)
        // results in an array [ r, g, b, a ] which has 4 tensor3D (in fact, they should be
        // viewed as tensor1D).
        let theLastAxisId = ( scaledInput.shape.length - 1 );  // Or, ( scaledInput.rank - 1 )

        // For a 4 color (r-g-b-a) channel image, splitCount will be 4.
        //
        // This should be the same as this.inChannels.
        let splitCount = scaledInput.shape[ theLastAxisId ];

        // Extract vocabulary indices from input. (In fact, the result is still tensor3D but has only one channel.)
        const vocabularyIndicesOneChannelTensor3DArray = tf.tidy( "VocabularyIndicesArray", () => {

          // Split the last axis (of input) as many as the shape size (of the last axis) (i.e. become tensor2D).
          // And then convert to integer, so that they can be used as tf.gather()'s indices.
          return scaledInput.split( splitCount, theLastAxisId ).map( t => t.toInt() );
        });

  //!!! (2020/05/16 Remarked) ...Old... Needs (inverted) residual connection
  //       // Embedding (looking up different vocabulary tables according to channel index of vocabulary indices).
  //       // Every tensor2D (i,e, one channel) will be expanded to tensor3D (i.e. multiple channels).
  //       const embeddedTensor3DArray = vocabularyIndicesTensor2DArray.map( ( vocabularyIndicesTensor2D, channelIndex ) => {
  //         this.vocabularyTablesTensors[ channelIndex ].gather( vocabularyIndicesTensor2D );
  //       });

        // Embedding (looking up different vocabulary tables according to channel index of vocabulary indices).
        let embeddedTensor3DArray = [];
        for ( let i = 0; i < splitCount; ++i ) {
          // Include the original input channel as residual connection.
          let oneChannelTensor3D = vocabularyIndicesOneChannelTensor3DArray[ i ];
          embeddedTensor3DArray.push( oneChannelTensor3D );

          // Every tensor2D (i.e. one channel) will be expanded to tensor3D (i.e. multiple channels).
          const multipleChannelTensor3D = this.vocabularyTablesTensor2DArray[ i ].gather( oneChannelTensor3D );
          embeddedTensor3DArray.push( multipleChannelTensor3D );
        }

  //!!! ...unfinished... squeeze-and-excitation.

        // Concatenate along the last axis, so that it is still tensor3D but with embedded (more) channels in the last axis.
        return tf.concat( embeddedTensor3DArray, theLastAxisId );

      } catch ( e ) {
      }
    });

    return predictResult;
  }

  get byteOffsetBegin() { return this.params.defaultByteOffsetBegin; }
  get byteOffsetEnd()   { return this.vocabularyTables[ this.params.inChannels - 1 ].defaultByteOffsetEnd; }

  get inChannels()                           { return this.params.inChannels; }
  get embeddingChannelCountPerInputChannel() { return this.params.channelMultiplier; }
}
<commit_msg>Update Embedding2D.js<commit_after>import * as Weights from "../Weights.js";

export { Params, Layer };

/**
 * Embedding (2D) layer parameters.
 */
class Params extends Weights.Params {

  /**
   * @param {number} channelMultiplier
   *   Every input channel will be expanded into so many embedding channels. The outChannels (output channel count)
   * is always depending on channelMultiplier and equal to ( inChannels * channelMultiplier ). If null, it will be
   * extracted from inputFloat32Array (i.e. by evolution).
   *
   * @return {boolean} Return false, if initialization failed.
   *
   * @override
   */
  init( inputFloat32Array, byteOffsetBegin, inChannels, channelMultiplier = null ) {

//!!! ...unfinished...
// inverted residual connection (by add or by concatenate) ? (dense net)
// squeeze-and-excitation ?
// Shuffled Grouped Pointwise Convolution ... ? (by tf.gather() ?)

    let parameterMap = new Map( [
      [ Weights.Params.Keys.inChannels,        inChannels ],
      [ Weights.Params.Keys.channelMultiplier, channelMultiplier ],

      // For an embedding layer, its output channel count always depends on channelMultiplier.
      [ Weights.Params.Keys.outChannels,       Infinity ],
    ] );

    return super.init( inputFloat32Array, byteOffsetBegin, parameterMap );
  }

}

/**
 * An embedding layer contains one params (this.params) and inChannels embedding vocabulary tables.
 * Every input channel has one embedding vocabulary table. Every embedding vocabulary table has
 * vocabularyCountPerInputChannel vocabularies. Every vocabulary has channelMultiplier embedding channels.
 *
 * @member {Array of number} inputScaleToSize
 *   Scale the height and width of the input image to size [ inputScaleToHeight, inputScaleToWidth ]
 * (in pixels) before convoluting. For text input, the inputScaleToHeight should be 1. If null, there will be
 * no scaling when predict().
 *
 * @member {number} vocabularyCountPerInputChannel
 *   Every input channel will have how many vocabularies. This is also vocabulary count per vocabulary table (because
 * every input channel has a vocabulary table). For an image data (R-G-B-A four channels), there will be 256
 * vocabularies per input channel because every channel is represented by one byte (8 bits) which has 2^8 = 256 kinds
 * of possible values.
 *
 * @member {number} embeddingChannelCountPerInputChannel
 *   Every vocabulary will have how many embedding channels. Every input channel will be expanded into so many
 * embedding channels. This is same as the this.params.channelMultiplier.
 */
class Layer {

  /**
   * @param {Float32Array} inputFloat32Array
   *   A Float32Array whose values will be interpret as weights.
   *
   * @param {number} byteOffsetBegin
   *   The position to start to decode from the inputFloat32Array. This is relative to the inputFloat32Array.buffer
   * (not to the inputFloat32Array.byteOffset).
   *
   * @param {number} inChannels
   *   The input channel count.
   *
   * @param {number} channelMultiplier
   *   Every vocabulary will have how many embedding channels. Every input channel will be expanded into so many
   * embedding channels. The outChannels (output channel count) is always depending on channelMultiplier and equal
   * to ( inChannels * channelMultiplier ). If null, it will be extracted from inputFloat32Array (i.e. by evolution).
   *
   * @return {boolean} Return false, if initialization failed.
   */
  init(
    inputFloat32Array, byteOffsetBegin,
    inputScaleToSize, inChannels, vocabularyCountPerInputChannel, channelMultiplier = null ) {

//!!! ...unfinished...
// inverted residual connection (by add or by concatenate) ? (dense net)
// squeeze-and-excitation ?
// Shuffled Grouped Pointwise Convolution ... ? (by tf.gather() ?)

    disposeTensors();
    this.params = this.vocabularyTables = null; // So that distinguishable if re-initialization failed.

    this.inputScaleToSize = inputScaleToSize;
    this.vocabularyCountPerInputChannel = vocabularyCountPerInputChannel;

    this.params = new Params();
    if ( !this.params.init( inputFloat32Array, byteOffsetBegin, inChannels, channelMultiplier ) )
      return false;

    let embeddingChannelCountPerInputChannel = this.embeddingChannelCountPerInputChannel; // The real channelMultiplier.
    let vocabularyTableShape = [ vocabularyCountPerInputChannel, embeddingChannelCountPerInputChannel ];

    // Extract data of vocabulary tables.
    this.vocabularyTables = new Array( inChannels );
    {
      let nextByteOffsetBegin = this.params.defaultByteOffsetEnd;
      for ( let i = 0; i < inChannels; ++i ) {
        this.vocabularyTables[ i ] = new Weights.Base();
        if ( !this.vocabularyTables[ i ].init( inputFloat32Array, nextByteOffsetBegin, null, 0, vocabularyTableShape ) )
          return false;  // e.g. input array do not have enough data.
        nextByteOffsetBegin = this.vocabularyTables[ i ].defaultByteOffsetEnd;
      }
    }

    // Build tf.tensor of vocabulary tables.
    try {
      this.vocabularyTablesTensor2DArray = tf.tidy( "Embedding2D.Layer.init.vocabularyTablesTensor2DArray", () => {

        let theLastAxisId = ( vocabularyTableShape.length - 1 ); // e.g. will be 1 for tensor2d.

        // Create vocabulary id list. (tensor1d)
        const vocabularyIdsTensor1d
          = tf.linspace( 0, ( vocabularyCountPerInputChannel - 1 ), vocabularyCountPerInputChannel );

        // Convert vocabulary id list to tensor2d. (for concatenating with vocabulary table)
        const vocabularyIdsTensor2d = vocabularyIdsTensor1d.expandDims( theLastAxisId );

        return this.vocabularyTables.map( ( vocabularyTable, i ) => {
          return tf.tidy( "Embedding2D.Layer.init.vocabularyTableWithId", () => {

            // Create an embedding vocabulary table (without vocabulary id).
            const vocabularyTable = tf.tensor2d( vocabularyTable, vocabularyTableShape );

            // Concatenate vocabulary id prefix vocabulary table.
            //
            // This is a residual connection for embedding layer. This concatenating uses some GPU memory space.
            // It, however, reduces some calculation time when predict() because the residual connection is already
            // created in advance (here).
            const vocabularyTableWithId = vocabularyIdsTensor2d.concat( vocabularyTable );
            retrun vocabularyTableWithId;
          });
        });
      });
    } catch ( e ) {
      return false; // e.g. out of (GPU) memory.
    }

    return true;
  }

  isValid() {
    if ( this.vocabularyTablesTensor2DArray )
      if ( this.vocabularyTablesTensor2DArray[ this.params.inChannels - 1 ] ) // At least, there should be one vocabulary table.
        if ( this.vocabularyTablesTensor2DArray[ this.params.inChannels - 1 ].isValid() )  // the last vocabulary table is valid.

          this.vocabularyTablesTensors
          return true;
    return false;
  }

  /** Release tf.tensor. */
  disposeTensors() {
    if ( this.vocabularyTablesTensor2DArray ) {
      tf.dispose( this.vocabularyTablesTensor2DArray );
      this.vocabularyTablesTensor2DArray = null;
    }
  }

  /**
   * Process the input and produce output by using the weights of this neural network layer.
   *
   * @param {tf.tensor3D} inputTensor3D
   *   A tensor3D data (e.g. height-width-color for color image, or 1-width-1 for text) with
   * this.inChannels (e.g. 4 for r-g-b-a, or 1 for text) channels.
   *
   * @return {tf.tensor3D} The predicted output as tensor3D. Return null, if failed (e.g. out of GPU memory).
   */
  predict( inputTensor3D ) {
    const predictResult = tf.tidy( "Embedding2D.Layer.predict", () => {
      try {

        // Scale input into specific size.
        let scaledInput;
        if (   ( !this.inputScaleToSize )                                       // No scaling information.
            || (   ( this.inputScaleToSize[ 0 ] == inputTensor3D.shape[ 0 ] )   // Or, already same size.
                && ( this.inputScaleToSize[ 1 ] == inputTensor3D.shape[ 1 ] ) )
           ) {
          scaledInput = inputTensor3D;
        } else {
          // Otherwise, scaling by using ( alignCorners == true ) for better looking when visualizing.
          scaledInput = inputTensor3D.resizeBilinear( inputTensor3D, this.inputScaleToSize, true );
        }

        // For example, suppose input is a color image (i.e. height-width-color tensor3D). The last
        // axis is a 4 color (r-g-b-a) channel. Splitting along the last axis (the color channel)
        // results in an array [ r, g, b, a ] which has 4 tensor3D (in fact, they should be
        // viewed as tensor1D).
        let theLastAxisId = ( scaledInput.shape.length - 1 );  // Or, ( scaledInput.rank - 1 )

        // For a 4 color (r-g-b-a) channel image, splitCount will be 4.
        //
        // This should be the same as this.inChannels.
        let splitCount = scaledInput.shape[ theLastAxisId ];

        // Extract vocabulary indices from input. (In fact, the result is still tensor3D but has only one channel.)
        const vocabularyIndicesOneChannelTensor3DArray = tf.tidy( "VocabularyIndicesArray", () => {

          // Split the last axis (of input) as many as the shape size (of the last axis) (i.e. become tensor2D).
          // And then convert to integer, so that they can be used as tf.gather()'s indices.
          return scaledInput.split( splitCount, theLastAxisId ).map( t => t.toInt() );
        });

        // Embedding (looking up different vocabulary tables according to channel index of vocabulary indices).
        // Every tensor3D (one channel) will be expanded to tensor3D (multiple channels).
        //
        // Note: this.vocabularyTablesTensor2DArray[] already be prefixed vocabulary id (when init()). So it
        // has residual connection in advance.
        const embeddedTensor3DArray = vocabularyIndicesOneChannelTensor3DArray.map(
          ( oneChannelTensor3D, channelIndex ) => {
            return this.vocabularyTablesTensor2DArray[ channelIndex ].gather( oneChannelTensor3D );
        });

//!!! (2020/05/16 Remarked) ...Old... Already residual connection when init().
//         // Embedding (looking up different vocabulary tables according to channel index of vocabulary indices).
//         let embeddedTensor3DArray = [];
//         for ( let i = 0; i < splitCount; ++i ) {
//           // Include the original input channel as residual connection.
//           let oneChannelTensor3D = vocabularyIndicesOneChannelTensor3DArray[ i ];
//           embeddedTensor3DArray.push( oneChannelTensor3D );
//
//           // Every tensor2D (i.e. one channel) will be expanded to tensor3D (i.e. multiple channels).
//           const multipleChannelTensor3D = this.vocabularyTablesTensor2DArray[ i ].gather( oneChannelTensor3D );
//           embeddedTensor3DArray.push( multipleChannelTensor3D );
//         }

//!!! ...unfinished... squeeze-and-excitation.

        // Concatenate along the last axis, so that it is still tensor3D but with embedded (more) channels in the last axis.
        return tf.concat( embeddedTensor3DArray, theLastAxisId );

      } catch ( e ) {
      }
    });

    return predictResult;
  }

  get byteOffsetBegin() { return this.params.defaultByteOffsetBegin; }
  get byteOffsetEnd()   { return this.vocabularyTables[ this.params.inChannels - 1 ].defaultByteOffsetEnd; }

  get inChannels()                           { return this.params.inChannels; }
  get embeddingChannelCountPerInputChannel() { return this.params.channelMultiplier; }
}
<|endoftext|>


<commit_before>module.exports = {
    env: {
        browser: true,
        es6: true,
    },
    parser: "@typescript-eslint/parser",
    parserOptions: {
        project: "tsconfig.json",
        sourceType: "module",
    },
    plugins: [
        "eslint-plugin-jsdoc",
        "@typescript-eslint",
        "@typescript-eslint/tslint",
        "prettier",
        "react-hooks",
    ],
    extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
    rules: {
        // Recommended rules with errors
        // TODO: Fix these and re-enable them

        "@typescript-eslint/ban-types": "off", // 35 errors
        "@typescript-eslint/explicit-module-boundary-types": "off", // 1242 warnings
        "@typescript-eslint/no-empty-interface": "off", // 45 errors
        "@typescript-eslint/no-explicit-any": "off", // 535 warnings
        "@typescript-eslint/no-namespace": "off", // 1 error
        "@typescript-eslint/no-this-alias": "off", // 4 errors
        "@typescript-eslint/triple-slash-reference": "off", // 1 error

        "no-misleading-character-class": "off", // 2 errors
        "no-prototype-builtins": "off", // 8 errors
        "no-self-assign": "off", // 2 errors
        "no-useless-escape": "off", // 24 errors
        "prefer-spread": "off", // 7 errors

        //==============================================================

        "@typescript-eslint/adjacent-overload-signatures": "error",
        "@typescript-eslint/consistent-type-assertions": "error",
        "@typescript-eslint/member-delimiter-style": "error",
        "@typescript-eslint/no-floating-promises": "error",
        "@typescript-eslint/no-inferrable-types": [
            "error",
            {
                ignoreParameters: true,
                ignoreProperties: true,
            },
        ],
        "@typescript-eslint/no-unused-vars": [
            "error",
            {
                varsIgnorePattern: "^_[a-zA-Z_]",
                argsIgnorePattern: "^_[a-zA-Z_]",
            },
        ],
        "@typescript-eslint/no-var-requires": "error",
        "@typescript-eslint/prefer-namespace-keyword": "error",
        "@typescript-eslint/semi": "error",
        "@typescript-eslint/type-annotation-spacing": "error",
        "computed-property-spacing": ["error", "never"],
        curly: "error",
        "eol-last": "error",
        eqeqeq: ["error", "smart"],
        "id-denylist": [
            "error",
            "any",
            "Number",
            "number",
            "String",
            "string",
            "Boolean",
            "boolean",
            "Undefined",
            "undefined",
        ],
        "id-match": "error",
        "jsdoc/check-alignment": "error",
        "jsdoc/require-asterisk-prefix": "error",
        "linebreak-style": ["error", "unix"],
        "no-caller": "error",
        "no-cond-assign": "error",
        "no-debugger": "error",
        "no-eval": "error",
        "no-fallthrough": [
            "error",
            {
                commentPattern: "break[\\s\\w]*omitted",
            },
        ],
        // Using the typescript-eslint version of this rule because of class
        // properties, which are not yet supported in ESLint.  For more info,
        // see: https://github.com/typescript-eslint/typescript-eslint/issues/491
        "@typescript-eslint/no-invalid-this": "error",
        "no-multiple-empty-lines": [
            "error",
            {
                max: 3,
            },
        ],
        "no-new-wrappers": "error",
        "no-tabs": "error",
        "no-trailing-spaces": "error",
        "no-undef-init": "error",
        "no-unsafe-finally": "error",
        "no-unused-labels": "error",
        "no-var": "error",
        "one-var": ["error", "never"],
        "prefer-arrow-callback": ["error", { allowNamedFunctions: true }],
        "prettier/prettier": "error",
        "use-isnan": "error",
        "@typescript-eslint/tslint/config": [
            "error",
            {
                rules: {
                    "file-header": [true, "[Cc]opyright ([(][Cc][)])?\\s*\\d{4}"],
                    "import-spacing": true,
                    whitespace: [
                        true,
                        "check-branch",
                        "check-decl",
                        "check-operator",
                        "check-separator",
                    ],
                },
            },
        ],
        "react-hooks/rules-of-hooks": "error",
        "prefer-const": [
            "error",
            {
                destructuring: "all",
            },
        ],
    },
    overrides: [
        {
            files: ["*.test.ts", "*.test.tsx"],
            // since test files are not part of tsconfig.json,
            // parserOptions.project must be unset
            parserOptions: {
                project: null,
            },
            rules: {
                // rules that depend on type information (and therefore
                // parserOptions.project)
                "@typescript-eslint/no-floating-promises": "off",
                "@typescript-eslint/tslint/config": "off",
            },
        },
    ],
};
<commit_msg>Note in eslintrc that we should investigate our exhaustive-deps warnings<commit_after>module.exports = {
    env: {
        browser: true,
        es6: true,
    },
    parser: "@typescript-eslint/parser",
    parserOptions: {
        project: "tsconfig.json",
        sourceType: "module",
    },
    plugins: [
        "eslint-plugin-jsdoc",
        "@typescript-eslint",
        "@typescript-eslint/tslint",
        "prettier",
        "react-hooks",
    ],
    extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
    rules: {
        // Recommended rules with errors
        // TODO: Fix these and re-enable them

        "@typescript-eslint/ban-types": "off", // 35 errors
        "@typescript-eslint/explicit-module-boundary-types": "off", // 1242 warnings
        "@typescript-eslint/no-empty-interface": "off", // 45 errors
        "@typescript-eslint/no-explicit-any": "off", // 535 warnings
        "@typescript-eslint/no-namespace": "off", // 1 error
        "@typescript-eslint/no-this-alias": "off", // 4 errors
        "@typescript-eslint/triple-slash-reference": "off", // 1 error

        "no-misleading-character-class": "off", // 2 errors
        "no-prototype-builtins": "off", // 8 errors
        "no-self-assign": "off", // 2 errors
        "no-useless-escape": "off", // 24 errors
        "prefer-spread": "off", // 7 errors
        "react-hooks/exhaustive-deps": "off", // 41 errors

        //==============================================================

        "@typescript-eslint/adjacent-overload-signatures": "error",
        "@typescript-eslint/consistent-type-assertions": "error",
        "@typescript-eslint/member-delimiter-style": "error",
        "@typescript-eslint/no-floating-promises": "error",
        "@typescript-eslint/no-inferrable-types": [
            "error",
            {
                ignoreParameters: true,
                ignoreProperties: true,
            },
        ],
        "@typescript-eslint/no-unused-vars": [
            "error",
            {
                varsIgnorePattern: "^_[a-zA-Z_]",
                argsIgnorePattern: "^_[a-zA-Z_]",
            },
        ],
        "@typescript-eslint/no-var-requires": "error",
        "@typescript-eslint/prefer-namespace-keyword": "error",
        "@typescript-eslint/semi": "error",
        "@typescript-eslint/type-annotation-spacing": "error",
        "computed-property-spacing": ["error", "never"],
        curly: "error",
        "eol-last": "error",
        eqeqeq: ["error", "smart"],
        "id-denylist": [
            "error",
            "any",
            "Number",
            "number",
            "String",
            "string",
            "Boolean",
            "boolean",
            "Undefined",
            "undefined",
        ],
        "id-match": "error",
        "jsdoc/check-alignment": "error",
        "jsdoc/require-asterisk-prefix": "error",
        "linebreak-style": ["error", "unix"],
        "no-caller": "error",
        "no-cond-assign": "error",
        "no-debugger": "error",
        "no-eval": "error",
        "no-fallthrough": [
            "error",
            {
                commentPattern: "break[\\s\\w]*omitted",
            },
        ],
        // Using the typescript-eslint version of this rule because of class
        // properties, which are not yet supported in ESLint.  For more info,
        // see: https://github.com/typescript-eslint/typescript-eslint/issues/491
        "@typescript-eslint/no-invalid-this": "error",
        "no-multiple-empty-lines": [
            "error",
            {
                max: 3,
            },
        ],
        "no-new-wrappers": "error",
        "no-tabs": "error",
        "no-trailing-spaces": "error",
        "no-undef-init": "error",
        "no-unsafe-finally": "error",
        "no-unused-labels": "error",
        "no-var": "error",
        "one-var": ["error", "never"],
        "prefer-arrow-callback": ["error", { allowNamedFunctions: true }],
        "prettier/prettier": "error",
        "use-isnan": "error",
        "@typescript-eslint/tslint/config": [
            "error",
            {
                rules: {
                    "file-header": [true, "[Cc]opyright ([(][Cc][)])?\\s*\\d{4}"],
                    "import-spacing": true,
                    whitespace: [
                        true,
                        "check-branch",
                        "check-decl",
                        "check-operator",
                        "check-separator",
                    ],
                },
            },
        ],
        "react-hooks/rules-of-hooks": "error",
        "prefer-const": [
            "error",
            {
                destructuring: "all",
            },
        ],
    },
    overrides: [
        {
            files: ["*.test.ts", "*.test.tsx"],
            // since test files are not part of tsconfig.json,
            // parserOptions.project must be unset
            parserOptions: {
                project: null,
            },
            rules: {
                // rules that depend on type information (and therefore
                // parserOptions.project)
                "@typescript-eslint/no-floating-promises": "off",
                "@typescript-eslint/tslint/config": "off",
            },
        },
    ],
};
<|endoftext|>