<commit_before>
import Encoder from '../Encoder'
import MathUtil from '../MathUtil'

const meta = {
  name: 'caesar-cipher',
  title: 'Caesar cipher',
  category: 'Ciphers',
  type: 'encoder'
}

const defaultAlphabet = 'abcdefghijklmnopqrstuvwxyz'
const defaultShift = 7

/**
 * Encoder brick for Caesar Cipher encoding and decoding
 */
export default class CaesarCipherEncoder extends Encoder {
  /**
   * Returns brick meta.
   * @return {object}
   */
  static getMeta () {
    return meta
  }

  /**
   * Constructor
   */
  constructor () {
    super()
    this.addSettings([
      {
        name: 'shift',
        type: 'number',
        label: 'Shift',
        priority: 10,
        value: defaultShift,
        integer: true,
        useBigInt: true,
        describeValue: this.describeShiftValue.bind(this),
        randomizeValue: this.randomizeShiftValue.bind(this)
      },
      {
        name: 'alphabet',
        type: 'text',
        value: defaultAlphabet,
        uniqueChars: true,
        minLength: 2,
        caseSensitivity: false,
        randomizable: false
      },
      {
        name: 'caseStrategy',
        type: 'enum',
        value: 'maintain',
        elements: ['maintain', 'ignore', 'strict'],
        labels: ['Maintain case', 'Ignore case', 'Strict (A ≠ a)'],
        width: 6,
        randomizable: false
      },
      {
        name: 'includeForeignChars',
        type: 'boolean',
        label: 'Foreign Chars',
        width: 6,
        value: true,
        trueLabel: 'Include',
        falseLabel: 'Ignore',
        randomizable: false
      }
    ])
  }

  /**
   * Performs encode or decode on given content.
   * @param {Chain} content
   * @param {boolean} isEncode True for encoding, false for decoding
   * @return {number[]|string|Uint8Array|Chain} Resulting content
   */
  performTranslate (content, isEncode) {
    const { shift, caseStrategy, includeForeignChars } =
      this.getSettingValues()

    // Prepare alphabet(s) depending on chosen case strategy
    let alphabet = this.getSettingValue('alphabet')
    let uppercaseAlphabet
    if (caseStrategy !== 'strict') {
      alphabet = alphabet.toLowerCase()
      uppercaseAlphabet = alphabet.toUpperCase()
    }

    const m = alphabet.getLength()
    const n = content.getLength()
    const result = new Array(n)

    let codePoint, x, y, uppercase
    let j = 0

    // Go through each character in content
    for (let i = 0; i < n; i++) {
      codePoint = content.getCodePointAt(i)

      // Match alphabet character
      x = alphabet.indexOfCodePoint(codePoint)
      uppercase = false

      // Match uppercase alphabet character (depending on case strategy)
      if (x === -1 && caseStrategy !== 'strict') {
        x = uppercaseAlphabet.indexOfCodePoint(codePoint)
        uppercase = true
      }

      if (x === -1) {
        // Character is not in the alphabet
        if (includeForeignChars) {
          result[j++] = codePoint
        }
      } else {
        // Shift character
        if (typeof shift !== 'bigint') {
          y = MathUtil.mod(x + shift * (isEncode ? 1 : -1), m)
        } else {
          y = Number(MathUtil.mod(
            BigInt(x) + shift * (isEncode ? 1n : -1n),
            BigInt(m)
          ))
        }

        // Translate index to character following the case strategy
        if (caseStrategy === 'maintain' && uppercase) {
          result[j++] = uppercaseAlphabet.getCodePointAt(y)
        } else {
          result[j++] = alphabet.getCodePointAt(y)
        }
      }
    }

    return result.slice(0, j)
  }

  /**
   * Triggered when a setting field has changed.
   * @param {Field} setting Sender setting field
   * @param {mixed} value New field value
   */
  settingValueDidChange (setting, value) {
    switch (setting.getName()) {
      case 'caseStrategy':
        // Apply case sensitivity on the alphabet setting
        this.getSetting('alphabet').setCaseSensitivity(value === 'strict')
        break
      case 'alphabet':
        // The shift value description depends on the alphabet and thus needs
        // to be updated when the alphabet changes
        this.getSetting('shift').setNeedsValueDescriptionUpdate()
        break
    }
  }

  /**
   * Generates a random shift setting value.
   * @param {Random} random Random instance
   * @param {Field} setting Shift setting
   * @return {string} Randomized plugboard setting value
   */
  randomizeShiftValue (random, setting) {
    const alphabetSetting = this.getSetting('alphabet')
    if (alphabetSetting.isValid()) {
      return random.nextInteger(1, alphabetSetting.getValue().getLength() - 1)
    }
    return null
  }

  /**
   * Function describing the given shift value in a human-readable way.
   * @param {number} value Field value
   * @param {Field} setting Sender
   * @return {?string} Shift label
   */
  describeShiftValue (value, setting) {
    // The shift value description depends on the alphabet setting
    if (!this.getSetting('alphabet').isValid()) {
      return null
    }

    // Shift the first character of the alphabet to describe the translation
    const { alphabet, shift } = this.getSettingValues()
    const plain = alphabet.getCharAt(0)
    const index = MathUtil.mod(
      shift,
      typeof shift !== 'bigint'
        ? alphabet.getLength()
        : BigInt(alphabet.getLength())
    )
    const encoded = alphabet.getCharAt(index)
    return `${plain}→${encoded}`
  }
}
<commit_msg>Remove BigInt literals not supported by Safari<commit_after>
import Encoder from '../Encoder'
import MathUtil from '../MathUtil'

const meta = {
  name: 'caesar-cipher',
  title: 'Caesar cipher',
  category: 'Ciphers',
  type: 'encoder'
}

const defaultAlphabet = 'abcdefghijklmnopqrstuvwxyz'
const defaultShift = 7

/**
 * Encoder brick for Caesar Cipher encoding and decoding
 */
export default class CaesarCipherEncoder extends Encoder {
  /**
   * Returns brick meta.
   * @return {object}
   */
  static getMeta () {
    return meta
  }

  /**
   * Constructor
   */
  constructor () {
    super()
    this.addSettings([
      {
        name: 'shift',
        type: 'number',
        label: 'Shift',
        priority: 10,
        value: defaultShift,
        integer: true,
        useBigInt: true,
        describeValue: this.describeShiftValue.bind(this),
        randomizeValue: this.randomizeShiftValue.bind(this)
      },
      {
        name: 'alphabet',
        type: 'text',
        value: defaultAlphabet,
        uniqueChars: true,
        minLength: 2,
        caseSensitivity: false,
        randomizable: false
      },
      {
        name: 'caseStrategy',
        type: 'enum',
        value: 'maintain',
        elements: ['maintain', 'ignore', 'strict'],
        labels: ['Maintain case', 'Ignore case', 'Strict (A ≠ a)'],
        width: 6,
        randomizable: false
      },
      {
        name: 'includeForeignChars',
        type: 'boolean',
        label: 'Foreign Chars',
        width: 6,
        value: true,
        trueLabel: 'Include',
        falseLabel: 'Ignore',
        randomizable: false
      }
    ])
  }

  /**
   * Performs encode or decode on given content.
   * @param {Chain} content
   * @param {boolean} isEncode True for encoding, false for decoding
   * @return {number[]|string|Uint8Array|Chain} Resulting content
   */
  performTranslate (content, isEncode) {
    const { shift, caseStrategy, includeForeignChars } =
      this.getSettingValues()

    // Prepare alphabet(s) depending on chosen case strategy
    let alphabet = this.getSettingValue('alphabet')
    let uppercaseAlphabet
    if (caseStrategy !== 'strict') {
      alphabet = alphabet.toLowerCase()
      uppercaseAlphabet = alphabet.toUpperCase()
    }

    const m = alphabet.getLength()
    const n = content.getLength()
    const result = new Array(n)

    let codePoint, x, y, uppercase
    let j = 0

    // Go through each character in content
    for (let i = 0; i < n; i++) {
      codePoint = content.getCodePointAt(i)

      // Match alphabet character
      x = alphabet.indexOfCodePoint(codePoint)
      uppercase = false

      // Match uppercase alphabet character (depending on case strategy)
      if (x === -1 && caseStrategy !== 'strict') {
        x = uppercaseAlphabet.indexOfCodePoint(codePoint)
        uppercase = true
      }

      if (x === -1) {
        // Character is not in the alphabet
        if (includeForeignChars) {
          result[j++] = codePoint
        }
      } else {
        // Shift character
        if (typeof shift !== 'bigint') {
          y = MathUtil.mod(x + shift * (isEncode ? 1 : -1), m)
        } else {
          y = Number(MathUtil.mod(
            BigInt(x) + shift * BigInt(isEncode ? 1 : -1),
            BigInt(m)
          ))
        }

        // Translate index to character following the case strategy
        if (caseStrategy === 'maintain' && uppercase) {
          result[j++] = uppercaseAlphabet.getCodePointAt(y)
        } else {
          result[j++] = alphabet.getCodePointAt(y)
        }
      }
    }

    return result.slice(0, j)
  }

  /**
   * Triggered when a setting field has changed.
   * @param {Field} setting Sender setting field
   * @param {mixed} value New field value
   */
  settingValueDidChange (setting, value) {
    switch (setting.getName()) {
      case 'caseStrategy':
        // Apply case sensitivity on the alphabet setting
        this.getSetting('alphabet').setCaseSensitivity(value === 'strict')
        break
      case 'alphabet':
        // The shift value description depends on the alphabet and thus needs
        // to be updated when the alphabet changes
        this.getSetting('shift').setNeedsValueDescriptionUpdate()
        break
    }
  }

  /**
   * Generates a random shift setting value.
   * @param {Random} random Random instance
   * @param {Field} setting Shift setting
   * @return {string} Randomized plugboard setting value
   */
  randomizeShiftValue (random, setting) {
    const alphabetSetting = this.getSetting('alphabet')
    if (alphabetSetting.isValid()) {
      return random.nextInteger(1, alphabetSetting.getValue().getLength() - 1)
    }
    return null
  }

  /**
   * Function describing the given shift value in a human-readable way.
   * @param {number} value Field value
   * @param {Field} setting Sender
   * @return {?string} Shift label
   */
  describeShiftValue (value, setting) {
    // The shift value description depends on the alphabet setting
    if (!this.getSetting('alphabet').isValid()) {
      return null
    }

    // Shift the first character of the alphabet to describe the translation
    const { alphabet, shift } = this.getSettingValues()
    const plain = alphabet.getCharAt(0)
    const index = MathUtil.mod(
      shift,
      typeof shift !== 'bigint'
        ? alphabet.getLength()
        : BigInt(alphabet.getLength())
    )
    const encoded = alphabet.getCharAt(index)
    return `${plain}→${encoded}`
  }
}
<|endoftext|>


<commit_before>z.fn.hide = _each(function hide() {
	this.style.display = "none";
	return this;
});

z.fn.show = _each(function show() {
	this.style.display = "";
	return this;
});

z.fn.clone = function (deep) {
	var i = 0;

	if (deep === undefined || deep === null) {
		deep = false;
	}

	for (; i < this.length; i++) {
		this[i] = this[i].cloneNode(deep);
	}

	return this;
};

z.fn.html = function (value) {
	var i, l;

	if (value === undefined) {
		return this[0].innerHTML;
	}

	for (i = 0, l = this.length; i < l; i++) {
		this[i].innerHTML = value;
	}

	return this;
};

z.fn.text = function (value) {
	var i, l;

	if (value === undefined) {
		return this.textContent;
	}

	for (i = 0, l = this.length; i < l; i++) {
		this[i].textContent = value;
	}

	return this;
};

z.fn.getAttr = function (key) {
	if (!key) {
		throw new Error("First parameter of z#getAttr is required");
	}

	return this[0] && this[0].getAttribute(key);
};

z.fn.setAttr = _each(function (key, value) {
	if (!key) {
		throw new Error("First parameter of z#setAttr is required");
	} else if (value === undefined) {
		throw new Error("Second parameter of z#setAttr is required");
	}

	this.setAttribute(key, value);
	return this;
});

z.fn.attr = function (key, value) {
	if (value === undefined) {
		return this.getAttr(key);
	}

	this.setAttr(key, value);
	return this;
};

z.fn.replaceWith = z.fn.replace = _each(function (value) {
	if (value === undefined) {
		throw new Error("First parameter of z#replace is required");
	}

	this.outerHTML = value;
});

if ("classList" in document.documentElement) {
	z.fn.addClass = _each(function addClass(className) {
		this.classList.add(className);
	});

	z.fn.removeClass = _each(function removeClass(className) {
		this.classList.remove(className);
	});

	z.fn.toggleClass = _each(function toggleClass(className, force) {
		if (force === undefined) {
			this.classList.toggle(className);
			return;
		}

		this.classList[force ? "add" : "remove"](className);
	});
} else {
	z.fn.addClass = _each(function addClass(className) {
		this.className += " " + className;
	});

	z.fn.removeClass = _each(function removeClass(className) {
		this.className += this.className.replace(new RegExp("(^|\\b)" + className + "(\\b|$)", "g"), " ");
	});

	z.fn.toggleClass = function (className, force) {
		this[force ? "addClass" : "removeClass"](className);
		return this;
	};
}

z.fn.append = function (value) {
	var element, i = 0, l = this.length;

	if (value === undefined) {
		throw new Error("First parameter of z#append is required.");
	}

	if (typeof value === "string") {
		for (; i < l; i++) {
			this[i].insertAdjacentHTML('beforeend', value);
		}

		return this;
	}

	if (value instanceof zArray) {
		value = value[0];
	}

	for (; i < l; i++) {
		this[i].appendChild(value);
	}

	return this;
}

z.fn.prepend = function (value) {
	var element, i = 0, l = this.length;

	if (value === undefined) {
		throw new Error("First parameter of z#prepend is required.");
	}

	if (typeof value === "string") {
		for (; i < l; i++) {
			this[i].insertAdjacentHTML('afterbegin', value);
		}

		return this;
	}

	if (value instanceof zArray) {
		value = value[0];
	}

	for (; i < l; i++) {
		this[i].insertBefore(value, this[i].firstChild);
	}

	return this;
}

z.fn.css = function (rule, value) {
	var i = 0, l = this.length;

	if (rule === undefined) {
		throw new Error("First parameter of z#css is required.");
	}

	if (value === undefined) {
		return getComputedStyle(this[0])[rule];
	} else {
		rule = rule.replace(/-./g, function (result) {
		    return result.substr(1).toUpperCase();
		});

		for (; i < l; i++) {
			this[i].style[rule] = value;
		}
	}

	return this;
}<commit_msg>Added after(), remove() and empty()<commit_after>z.fn.hide = _each(function hide() {
	this.style.display = "none";
	return this;
});

z.fn.show = _each(function show() {
	this.style.display = "";
	return this;
});

z.fn.clone = function (deep) {
	var i = 0;

	if (deep === undefined || deep === null) {
		deep = false;
	}

	for (; i < this.length; i++) {
		this[i] = this[i].cloneNode(deep);
	}

	return this;
};

z.fn.html = function (value) {
	var i, l;

	if (value === undefined) {
		return this[0].innerHTML;
	}

	for (i = 0, l = this.length; i < l; i++) {
		this[i].innerHTML = value;
	}

	return this;
};

z.fn.text = function (value) {
	var i, l;

	if (value === undefined) {
		return this.textContent;
	}

	for (i = 0, l = this.length; i < l; i++) {
		this[i].textContent = value;
	}

	return this;
};

z.fn.getAttr = function (key) {
	if (!key) {
		throw new Error("First parameter of z#getAttr is required");
	}

	return this[0] && this[0].getAttribute(key);
};

z.fn.setAttr = _each(function (key, value) {
	if (!key) {
		throw new Error("First parameter of z#setAttr is required");
	} else if (value === undefined) {
		throw new Error("Second parameter of z#setAttr is required");
	}

	this.setAttribute(key, value);
	return this;
});

z.fn.attr = function (key, value) {
	if (value === undefined) {
		return this.getAttr(key);
	}

	this.setAttr(key, value);
	return this;
};

z.fn.replaceWith = z.fn.replace = _each(function (value) {
	if (value === undefined) {
		throw new Error("First parameter of z#replace is required");
	}

	this.outerHTML = value;
});

if ("classList" in document.documentElement) {
	z.fn.addClass = _each(function addClass(className) {
		this.classList.add(className);
	});

	z.fn.removeClass = _each(function removeClass(className) {
		this.classList.remove(className);
	});

	z.fn.toggleClass = _each(function toggleClass(className, force) {
		if (force === undefined) {
			this.classList.toggle(className);
			return;
		}

		this.classList[force ? "add" : "remove"](className);
	});
} else {
	z.fn.addClass = _each(function addClass(className) {
		this.className += " " + className;
	});

	z.fn.removeClass = _each(function removeClass(className) {
		this.className += this.className.replace(new RegExp("(^|\\b)" + className + "(\\b|$)", "g"), " ");
	});

	z.fn.toggleClass = function (className, force) {
		this[force ? "addClass" : "removeClass"](className);
		return this;
	};
}

z.fn.append = function (value) {
	var element, i = 0, l = this.length;

	if (value === undefined) {
		throw new Error("First parameter of z#append is required.");
	}

	if (typeof value === "string") {
		for (; i < l; i++) {
			this[i].insertAdjacentHTML('beforeend', value);
		}

		return this;
	}

	if (value instanceof zArray) {
		value = value[0];
	}

	for (; i < l; i++) {
		this[i].appendChild(value);
	}

	return this;
}

z.fn.prepend = function (value) {
	var element, i = 0, l = this.length;

	if (value === undefined) {
		throw new Error("First parameter of z#prepend is required.");
	}

	if (typeof value === "string") {
		for (; i < l; i++) {
			this[i].insertAdjacentHTML('afterbegin', value);
		}

		return this;
	}

	if (value instanceof zArray) {
		value = value[0];
	}

	for (; i < l; i++) {
		this[i].insertBefore(value, this[i].firstChild);
	}

	return this;
}

z.fn.after = function (value) {
	var element, i = 0, l = this.length;

	if (value === undefined) {
		throw new Error("First parameter of z#append is required.");
	}

	if (typeof value === "string") {
		for (; i < l; i++) {
			this[i].insertAdjacentHTML('afterend', value);
		}

		return this;
	}

	if (value instanceof zArray) {
		value = value[0];
	}

	for (; i < l; i++) {
		this[i].insertAdjacentHTML('afterend', value.outerHTML);
	}

	return this;
}

z.fn.css = function (rule, value) {
	var i = 0, l = this.length;

	if (rule === undefined) {
		throw new Error("First parameter of z#css is required.");
	}

	if (value === undefined) {
		return getComputedStyle(this[0])[rule];
	} else {
		rule = rule.replace(/-./g, function (result) {
		    return result.substr(1).toUpperCase();
		});

		for (; i < l; i++) {
			this[i].style[rule] = value;
		}
	}

	return this;
}

z.fn.remove = function () {
	var i = 0, l = this.length;

	for (; i < l; i++) {
		this[i].parentNode.removeChild(this[i]);
	}
}

z.fn.empty = function () {
	var i = 0, l = this.length;

	for (; i < l; i++) {
		this[i].innerHTML = '';
	}

	return this;
}<|endoftext|>


<commit_before>/*
    Rob Holme

    Class used to retrieve extension preferences

*/
const vscode = require('vscode');

//----------------------------------------------------
// class defining a single field value and the filename it was found in
class ExtensionPreferences {

	constructor() {
		this._config = vscode.workspace.getConfiguration('hl7tools');
	}

	get AddLineBreakOnActivation() {
		return this._config['AddLinebreakOnActivation']
	}

	get ConnectionTimeOut() {
		return this._config['ConnectionTimeout']
	}

	get DefaultListenerPort() {
		return this._config['DefaultListenerPort']
	}

	get DefaultRemoteHost() {
		return this._config['DefaultRemoteHost']
	}

	get FavouriteRemoteHosts() {
		return this._config['FavouriteRemoteHosts']
	}

	get HighlightBackgroundColour() {
		return this._config['highlightBackgroundColor']
	}

	get MaxLinesForFieldDescriptions() {
		return this._config['MaxLinesForFieldDescriptions']
	}

	get SendACK() {
		return this._config['SendACK']
	}

	get SocketEncodingPreference() {
		// select the socket encoding defined in the preferences
		switch (this._config['SocketEncoding']) {
			case "UTF-8":
				return "utf8";
			case "UTF-16LE":
				return "utf16le";
			case "ISO-8859-1":
				return "latin1";
			case "ASCII":
				return "ascii";
			default:
				return "utf8"
		}
	}

	get CustomSegmentSchema() {
		return this._config['CustomSegmentSchema']
	}

}

exports.ExtensionPreferences = ExtensionPreferences;<commit_msg>added check to return null if no 'favourites' preference is set<commit_after>/*
    Rob Holme

    Class used to retrieve extension preferences

*/
const vscode = require('vscode');

//----------------------------------------------------
// class defining a single field value and the filename it was found in
class ExtensionPreferences {

	constructor() {
		this._config = vscode.workspace.getConfiguration('hl7tools');
	}

	get AddLineBreakOnActivation() {
		return this._config['AddLinebreakOnActivation']
	}

	get ConnectionTimeOut() {
		return this._config['ConnectionTimeout']
	}

	get DefaultListenerPort() {
		return this._config['DefaultListenerPort']
	}

	get DefaultRemoteHost() {
		return this._config['DefaultRemoteHost']
	}

	get FavouriteRemoteHosts() {
		// return null if no preferences set (based on the first item not containing a description)
		if (this._config['FavouriteRemoteHosts'][0].Description) {
			return this._config['FavouriteRemoteHosts']
		}
		else {
			return null;
		}
	}

	get HighlightBackgroundColour() {
		return this._config['highlightBackgroundColor']
	}

	get MaxLinesForFieldDescriptions() {
		return this._config['MaxLinesForFieldDescriptions']
	}

	get SendACK() {
		return this._config['SendACK']
	}

	get SocketEncodingPreference() {
		// select the socket encoding defined in the preferences
		switch (this._config['SocketEncoding']) {
			case "UTF-8":
				return "utf8";
			case "UTF-16LE":
				return "utf16le";
			case "ISO-8859-1":
				return "latin1";
			case "ASCII":
				return "ascii";
			default:
				return "utf8"
		}
	}

	get CustomSegmentSchema() {
		return this._config['CustomSegmentSchema']
	}

}

exports.ExtensionPreferences = ExtensionPreferences;<|endoftext|>


<commit_before>const React = require("react");
const ReactDOM = require("react-dom");
const TestUtils = require("react-addons-test-utils");
const {shallow} = require("enzyme");

const {types, PlaceholderHighlightContext, HighlightContext} = require("components/HighlightContext/HighlightContext");

describe("HighlightContext", () => {
  let instance;
  let el;

  function setup(props = {type: "history"}) {
    instance = TestUtils.renderIntoDocument(<HighlightContext {...props} />);
    el = ReactDOM.findDOMNode(instance);
  }

  it("should render the component", () => {
    setup();
    TestUtils.isCompositeComponentWithType(instance, HighlightContext);
  });

  it("should render the right icon given a type", () => {
    setup({type: "bookmark"});
    assert.include(instance.refs.icon.className, `icon-${types.bookmark.icon}`);
  });

  it("should render props.icon if specified", () => {
    setup({type: "bookmark", icon: "foo"});
    assert.include(instance.refs.icon.className, "icon-foo");
  });

  it("should render the label defined by type if props.label is not specified", () => {
    setup({type: "bookmark"});
    assert.equal(instance.refs.label.textContent, types.bookmark.label);
  });

  it("should render props.label if specified", () => {
    setup({type: "bookmark", label: "My bookmark"});
    assert.equal(instance.refs.label.textContent, "My bookmark");
  });

  it("should render props.date if specified", () => {
    setup({type: "bookmark", date: Date.now()});
    assert.equal(instance.refs.timestamp.textContent, "<1m");
  });

  it("should not show a date if props.date is not specified", () => {
    setup({type: "bookmark"});
    assert.equal(instance.refs.timestamp.textContent, "");
  });

  it("should not show a tooltip if it is not defined by the type", () => {
    setup({type: "bookmark"});
    assert.isUndefined(instance.refs.tooltip);
  });

  it("should show a tooltip for recommended links", () => {
    setup({type: "recommended", date: Date.now()});
    assert.ok(instance.refs.tooltip);
    assert.equal(instance.refs.tooltip.props.label, types.recommended.tooltip);
  });

  it("should show not show a timestamps for recommended links", () => {
    setup({type: "recommended", date: Date.now()});
    assert.equal(instance.refs.timestamp.hidden, true);
  });

  it("should have a .tooltip-container class", () => {
    setup();
    assert.include(el.className, "tooltip-container");
  });
});

describe("PlaceholderHighlightContext", () => {
  it("should have a .placeholder class", () => {
    const wrapper = shallow(<PlaceholderHighlightContext />);

    assert.lengthOf(wrapper.find(".placeholder"), 1);
  });
});
<commit_msg>chore(testing: #1929 Port HighlightContext tests to enzyme<commit_after>const React = require("react");
const {shallow} = require("enzyme");

const Tooltip = require("components/Tooltip/Tooltip");
const {types, PlaceholderHighlightContext, HighlightContext} = require("components/HighlightContext/HighlightContext");

describe("HighlightContext", () => {
  let wrapper;

  function setup(props = {type: "history"}) {
    wrapper = shallow(<HighlightContext {...props} />);
  }

  it("should render the component", () => {
    setup();
    assert.instanceOf(wrapper.instance(), HighlightContext);
  });

  it("should render the right icon given a type", () => {
    setup({type: "bookmark"});
    assert.ok(wrapper.find(".icon").hasClass(`icon-${types.bookmark.icon}`));
  });

  it("should render props.icon if specified", () => {
    setup({type: "bookmark", icon: "foo"});
    assert.ok(wrapper.find(".icon").hasClass("icon-foo"));
  });

  it("should render the label defined by type if props.label is not specified", () => {
    setup({type: "bookmark"});
    assert.equal(wrapper.find(".hc-label").text(), types.bookmark.label);
  });

  it("should render props.label if specified", () => {
    setup({type: "bookmark", label: "My bookmark"});
    assert.equal(wrapper.find(".hc-label").text(), "My bookmark");
  });

  it("should render props.date if specified", () => {
    setup({type: "bookmark", date: Date.now()});
    assert.equal(wrapper.find(".hc-timestamp").text(), "<1m");
  });

  it("should not show a date if props.date is not specified", () => {
    setup({type: "bookmark"});
    assert.lengthOf(wrapper.find(".hc-timestamp").text(), 0);
  });

  it("should not show a tooltip if it is not defined by the type", () => {
    setup({type: "bookmark"});
    assert.lengthOf(wrapper.find(Tooltip), 0);
  });

  it("should show a tooltip for recommended links", () => {
    setup({type: "recommended", date: Date.now()});
    const tooltipWrapper = wrapper.find(Tooltip);

    assert.lengthOf(tooltipWrapper, 1);
    assert.equal(tooltipWrapper.prop("label"), types.recommended.tooltip);
  });

  it("should show not show a timestamps for recommended links", () => {
    setup({type: "recommended", date: Date.now()});
    assert.equal(wrapper.find(".hc-timestamp").prop("hidden"), true);
  });

  it("should have a .tooltip-container class", () => {
    setup();
    assert.ok(wrapper.hasClass("tooltip-container"));
  });
});

describe("PlaceholderHighlightContext", () => {
  it("should have a .placeholder class", () => {
    const wrapper = shallow(<PlaceholderHighlightContext />);

    assert.lengthOf(wrapper.find(".placeholder"), 1);
  });
});
<|endoftext|>


<commit_before>/*jslint node: true, white: true, sloppy: true */

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

// array of counters.
function extractCounters(metrics) {
  var counters = [];

  Object.keys(metrics.counters).forEach(function(name) {
    counters[name] = {
      name: name,
      value: metrics.counters[name]
    };
  });

  Object.keys(metrics.counter_rates).forEach(function(name) {
    counters[name].rate = metrics.counter_rates[name];
  });

  return Object.keys(counters).map(function(name) {
    return counters[name];
  });
}

// array of gauges.
function extractGauges(metrics) {
  var gauges = [];

  Object.keys(metrics.gauges).forEach(function(name) {
    gauges.push({
      name: name,
      value: metrics.gauges[name]
    });
  });

  return gauges;
}

// array of sets
function extractSets(metrics) {
  var sets = [];

  Object.keys(metrics.sets).forEach(function(name) {
    sets.push({
      name: name,
      values : Object.keys(metrics.sets[name].store)
    });
  });

  return sets;
}

function extractTimers(metrics) {
  var timers = {},
      hasPercentiles = metrics.hasOwnProperty('pctThreshold') && metrics.pctThreshold.length > 0;

  Object.keys(metrics.timers).forEach(function(name) {
    timers[name] = {
      name: name,
      count: metrics.timer_data[name].count == null ? 0 : metrics.timer_data[name].count,
      rate: metrics.timer_data[name].count_ps == null ? 0 : metrics.timer_data[name].count_ps,
      min: metrics.timer_data[name].lower == null ? 0 : metrics.timer_data[name].lower,
      max: metrics.timer_data[name].upper == null ? 0 : metrics.timer_data[name].upper,
      sum: metrics.timer_data[name].sum == null ? 0 : metrics.timer_data[name].sum,
      avg: metrics.timer_data[name].mean == null ? 0 : metrics.timer_data[name].mean,
      median: metrics.timer_data[name].median == null ? 0 : metrics.timer_data[name].median,
      std: metrics.timer_data[name].std == null ? 0 : metrics.timer_data[name].median
    };
    if (hasPercentiles) {
      timers[name].percentiles = {};
      metrics.pctThreshold.forEach(function(percentile) {
        // ensure we have a valid percentile before including it. I see nulls and partials all the time.
        var percentilesOk = true;
        ['mean_', 'upper_', 'sum_'].forEach(function(label) {
          percentilesOk = percentilesOk
            && metrics.timer_data[name].hasOwnProperty(label + percentile)
            && metrics.timer_data[name][label + percentile] !== null;
        });
        if (percentilesOk) {
          timers[name].percentiles[percentile] = {
            avg: metrics.timer_data[name]['mean_' + percentile],
            max: metrics.timer_data[name]['upper_' + percentile],
            sum: metrics.timer_data[name]['sum_' + percentile]

          }
        }
      });
    }
    if (metrics.timer_data[name].hasOwnProperty('histogram')) {
      // this timer has a histogram.
      timers[name]['histogram'] = metrics.timer_data[name].histogram;
    }

  });

  return Object.keys(timers).map(function(name) {
    return timers[name];
  });
}

function affixMetrics(tenantMetrics, tenantId) {
  if (!tenantMetrics.hasOwnProperty(tenantId)) {
    tenantMetrics[tenantId] = {
      gauges: [],
      counters: [],
      timers: [],
      sets: []
    };
  }
}

function groupMetricsByTenant(metrics) {
  var map = {
      'gauges': extractGauges(metrics),
      'counters': extractCounters(metrics),
      'timers': extractTimers(metrics),
      'sets': extractSets(metrics)
    },
      tenantMetrics = {},
      parts, tenantId, metricName, tenantPlusMetricName;

  Object.keys(map).forEach(function(metricType) {
    map[metricType].forEach(function(metric) {
      tenantPlusMetricName = metric.name;
      parts = tenantPlusMetricName.split('.');
      tenantId = parts.shift();
      metricName = parts.join('.');
      // rename the metric.
      metric.name = metricName;
      affixMetrics(tenantMetrics, tenantId);
      tenantMetrics[tenantId][metricType].push(metric);
    });
  });

  return tenantMetrics;
}

exports.extractCounters = extractCounters;
exports.extractGauges = extractGauges;
exports.extractSets = extractSets;
exports.extractTimers = extractTimers;
exports.groupMetricsByTenant = groupMetricsByTenant;
<commit_msg>fixing unit test by fixing a typo<commit_after>/*jslint node: true, white: true, sloppy: true */

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

// array of counters.
function extractCounters(metrics) {
  var counters = [];

  Object.keys(metrics.counters).forEach(function(name) {
    counters[name] = {
      name: name,
      value: metrics.counters[name]
    };
  });

  Object.keys(metrics.counter_rates).forEach(function(name) {
    counters[name].rate = metrics.counter_rates[name];
  });

  return Object.keys(counters).map(function(name) {
    return counters[name];
  });
}

// array of gauges.
function extractGauges(metrics) {
  var gauges = [];

  Object.keys(metrics.gauges).forEach(function(name) {
    gauges.push({
      name: name,
      value: metrics.gauges[name]
    });
  });

  return gauges;
}

// array of sets
function extractSets(metrics) {
  var sets = [];

  Object.keys(metrics.sets).forEach(function(name) {
    sets.push({
      name: name,
      values : Object.keys(metrics.sets[name].store)
    });
  });

  return sets;
}

function extractTimers(metrics) {
  var timers = {},
      hasPercentiles = metrics.hasOwnProperty('pctThreshold') && metrics.pctThreshold.length > 0;

  Object.keys(metrics.timers).forEach(function(name) {
    timers[name] = {
      name: name,
      count: metrics.timer_data[name].count == null ? 0 : metrics.timer_data[name].count,
      rate: metrics.timer_data[name].count_ps == null ? 0 : metrics.timer_data[name].count_ps,
      min: metrics.timer_data[name].lower == null ? 0 : metrics.timer_data[name].lower,
      max: metrics.timer_data[name].upper == null ? 0 : metrics.timer_data[name].upper,
      sum: metrics.timer_data[name].sum == null ? 0 : metrics.timer_data[name].sum,
      avg: metrics.timer_data[name].mean == null ? 0 : metrics.timer_data[name].mean,
      median: metrics.timer_data[name].median == null ? 0 : metrics.timer_data[name].median,
      std: metrics.timer_data[name].std == null ? 0 : metrics.timer_data[name].std
    };
    if (hasPercentiles) {
      timers[name].percentiles = {};
      metrics.pctThreshold.forEach(function(percentile) {
        // ensure we have a valid percentile before including it. I see nulls and partials all the time.
        var percentilesOk = true;
        ['mean_', 'upper_', 'sum_'].forEach(function(label) {
          percentilesOk = percentilesOk
            && metrics.timer_data[name].hasOwnProperty(label + percentile)
            && metrics.timer_data[name][label + percentile] !== null;
        });
        if (percentilesOk) {
          timers[name].percentiles[percentile] = {
            avg: metrics.timer_data[name]['mean_' + percentile],
            max: metrics.timer_data[name]['upper_' + percentile],
            sum: metrics.timer_data[name]['sum_' + percentile]

          }
        }
      });
    }
    if (metrics.timer_data[name].hasOwnProperty('histogram')) {
      // this timer has a histogram.
      timers[name]['histogram'] = metrics.timer_data[name].histogram;
    }

  });

  return Object.keys(timers).map(function(name) {
    return timers[name];
  });
}

function affixMetrics(tenantMetrics, tenantId) {
  if (!tenantMetrics.hasOwnProperty(tenantId)) {
    tenantMetrics[tenantId] = {
      gauges: [],
      counters: [],
      timers: [],
      sets: []
    };
  }
}

function groupMetricsByTenant(metrics) {
  var map = {
      'gauges': extractGauges(metrics),
      'counters': extractCounters(metrics),
      'timers': extractTimers(metrics),
      'sets': extractSets(metrics)
    },
      tenantMetrics = {},
      parts, tenantId, metricName, tenantPlusMetricName;

  Object.keys(map).forEach(function(metricType) {
    map[metricType].forEach(function(metric) {
      tenantPlusMetricName = metric.name;
      parts = tenantPlusMetricName.split('.');
      tenantId = parts.shift();
      metricName = parts.join('.');
      // rename the metric.
      metric.name = metricName;
      affixMetrics(tenantMetrics, tenantId);
      tenantMetrics[tenantId][metricType].push(metric);
    });
  });

  return tenantMetrics;
}

exports.extractCounters = extractCounters;
exports.extractGauges = extractGauges;
exports.extractSets = extractSets;
exports.extractTimers = extractTimers;
exports.groupMetricsByTenant = groupMetricsByTenant;
<|endoftext|>


<commit_before>import React from 'react';
import State from './state';
import throwError from './throw-error';

export default function(Component) {
    return class DataWatcher extends Component {
        static contextTypes = {
            state: React.PropTypes.instanceOf(State)
        };

        constructor(props, context) {
            super(props, context);

            this.cursors = {};
            this.dataState = context.state;

            if (typeof this.dataState === 'undefined') {
                throwError('missing state. It can happen if you forgot to set state in DataInit or using any decorator before DataInit', this.constructor.displayName);
            }

            this._initCursors(props, context);

            this.state = {
                ...this.state,
                data: this._getCurrentData()
            };

            this._updateDataState = this._updateDataState.bind(this);
        }

        componentDidMount() {
            if (super.componentDidMount) {
                super.componentDidMount();
            }

            Object.keys(this.cursors).forEach(branch => {
                this.dataState.addWaitingCursor(this.cursors[branch]);
            });

            this._updateDataState();
            this._dataWatch();
        }

        componentWillUnmount() {
            if (super.componentWillUnmount) {
                super.componentWillUnmount();
            }

            this._dataUnwatch();
        }

        _reloadData(props) {
            this._dataUnwatch();
            this._initCursors(props);
            this._updateDataState();
            this._dataWatch();
        }

        _resetData() {
            this._resetDataIn(Object.keys(this.cursors));
        }

        _resetDataIn(cursorsTypes) {
            cursorsTypes.forEach(cursorType => {
                const cursor = this.cursors[cursorType];

                if (cursor.exists()) {
                    cursor.unset();
                }
            });
            this._updateDataState();
        }

        _initCursors(props = this.props) {
            const stateTree = this.dataState.getTree();

            this.cursorPaths = this.constructor.data(props, this.state);

            Object.keys(this.cursorPaths)
                .filter(branch => {
                    return this.cursorPaths[branch].every(
                        pathChunk => typeof pathChunk !== 'undefined'
                    );
                })
                .forEach(branch => {
                    this.cursors[branch] = stateTree.select(this.cursorPaths[branch]);
                });
        }

        _dataWatch() {
            Object.keys(this.cursors).forEach(
                cursorType => this.cursors[cursorType].on('update', this._updateDataState)
            );
        }

        _dataUnwatch() {
            Object.keys(this.cursors).forEach(
                cursorType => this.cursors[cursorType].off('update', this._updateDataState)
            );
        }

        _getCurrentData() {
            const data = {};

            Object.keys(this.cursors).forEach(branch => {
                data[branch] = this.cursors[branch].get();
            });

            return data;
        }

        _updateDataState() {
            this.setState({
                data: this._getCurrentData()
            });
        }
    };
}
<commit_msg>:heavy_plus_sign: allow data depencies path to depend on other cursor paths<commit_after>import React from 'react';
import State from './state';
import throwError from './throw-error';

export default function(Component) {
    return class DataWatcher extends Component {
        static contextTypes = {
            state: React.PropTypes.instanceOf(State)
        };

        constructor(props, context) {
            super(props, context);

            this.cursors = {};
            this.dataState = context.state;

            if (typeof this.dataState === 'undefined') {
                throwError('missing state. It can happen if you forgot to set state in DataInit or using any decorator before DataInit', this.constructor.displayName);
            }

            this._initCursors(props, context);

            this.state = {
                ...this.state,
                data: this._getCurrentData()
            };

            this._updateDataState = this._updateDataState.bind(this);
        }

        componentDidMount() {
            if (super.componentDidMount) {
                super.componentDidMount();
            }

            Object.keys(this.cursors).forEach(branch => {
                this.dataState.addWaitingCursor(this.cursors[branch]);
            });

            this._updateDataState();
            this._dataWatch();
        }

        componentWillUnmount() {
            if (super.componentWillUnmount) {
                super.componentWillUnmount();
            }

            this._dataUnwatch();
        }

        _reloadData(props = this.props) {
            this._dataUnwatch();
            this._initCursors(props);
            this._updateDataState();
            this._dataWatch();
        }

        _resetData() {
            this._resetDataIn(Object.keys(this.cursors));
        }

        _resetDataIn(cursorsTypes) {
            cursorsTypes.forEach(cursorType => {
                const cursor = this.cursors[cursorType];

                if (cursor.exists()) {
                    cursor.unset();
                }
            });
            this._updateDataState();
        }

        _isValidPath(path) {
            return path.every(
                pathChunk => typeof pathChunk !== 'undefined'
            );
        }

        _prepareCursorPath(path) {
            const stateTree = this.dataState.getTree();

            return path.map(pathChunk => {
                if (Array.isArray(pathChunk)) {
                    const preparedCursorPath = this._prepareCursorPath(pathChunk);

                    if (!this._isValidPath(preparedCursorPath)) {
                        return;
                    }

                    const pathChunkCursor = stateTree.select(preparedCursorPath);

                    pathChunkCursor.once('update', ::this._reloadData);

                    return pathChunkCursor.get();
                }

                return pathChunk;
            });
        }

        _prepareCursorPaths(props) {
            const cursorPaths = this.constructor.data(props, this.state);

            Object.keys(cursorPaths).forEach(branch => {
                cursorPaths[branch] = this._prepareCursorPath(cursorPaths[branch]);
            });

            return cursorPaths;
        }

        _initCursors(props) {
            const stateTree = this.dataState.getTree();

            this.cursorPaths = this._prepareCursorPaths(props);

            Object.keys(this.cursorPaths)
                .filter(branch => this._isValidPath(this.cursorPaths[branch]))
                .forEach(branch => {
                    this.cursors[branch] = stateTree.select(this.cursorPaths[branch]);
                });
        }

        _dataWatch() {
            Object.keys(this.cursors).forEach(
                cursorType => this.cursors[cursorType].on('update', this._updateDataState)
            );
        }

        _dataUnwatch() {
            Object.keys(this.cursors).forEach(
                cursorType => this.cursors[cursorType].off('update', this._updateDataState)
            );
        }

        _getCurrentData() {
            const data = {};

            Object.keys(this.cursors).forEach(branch => {
                data[branch] = this.cursors[branch].get();
            });

            return data;
        }

        _updateDataState() {
            this.setState({
                data: this._getCurrentData()
            });
        }
    };
}
<|endoftext|>


<commit_before>var usmapvis = usmapvis || (function ($, d3, undefined) {
    /*
    * Default map settings
    */
    var defaults = {
        width: 1000,
        height: 600
    },
    /*
    * Creates Us Map for visualisation
    */
    createMap = function (target, opts) {
        return (function (target, opts) {
            // Set options
            opts = $.extend({}, defaults, opts);
            opts.radius = Math.min(opts.width, opts.height) / 3;

            // declare variables
            var visualisations = {},

                centroids = {},
                centered,

                projection = d3.geo.albersUsa()
                    .scale(opts.width)
                    .translate([opts.width / 2, opts.height / 2 + 20]),

                path = d3.geo.path()
                    .projection(projection),

                svg = target.append("svg")
                    .attr("width", opts.width)
                    .attr("height", opts.height),
                g = svg.append("g"),

                tooltip = d3.select("body")
                    .append("div")
                    .attr("class", "tooltip")
                    .style("opacity", 0),

                // Get us state data
                id_name_map = { 0: null },
                short_name_id_map = { 0: null },

                data_dfd = $.Deferred();

            console.log(target);
            console.log(svg);

            var initialize = function () {
                    // get us state names and codes
                    d3.tsv("data/us-state-names.tsv", function(error, names) {
                        names.forEach(function (name) {
                            id_name_map[name.id] = name;
                            short_name_id_map[name.code] = name.id;
                        });
                    });

                    createUsMap();

                    d3.tsv("data/SPPA82-12-filtered.tsv", function(data) {
                        // groups all data by state
                        var groups = d3.nest()
                            .key(function(d) {return d.fips_state})
                            .entries(data),
                            emptygroup = -1;

                        // Set groupname
                        groups.forEach(function (group, i) {
                            if (!group.key || group.key === "") return emptygroup = i;
                            group.name = id_name_map[short_name_id_map[group.key.toUpperCase()]].name;
                        });
                        // Remove non-state data group
                        groups.splice(emptygroup, 1);

                        data_dfd.resolve(groups);
                    });

                },

                createUsMap = function () {
                    // create visual map
                    d3.json("data/us.json", function(error, us) {
                        function clicked(d) {
                        }

                        g.append("g")
                            .attr("id", "states")
                            .selectAll("path")
                            .data(topojson.feature(us, us.objects.states).features)
                            .enter()
                            .append("g")
                            .attr("class","state-path")
                            .attr("state", function(d) {
                                return id_name_map[d.id].name;
                            })
                            .attr("id", function(d) {
                                return id_name_map[d.id].code;
                            });

                        svg.selectAll('.state-path')
                            .append("path")
                            .attr("d", path)
                            .attr("centroid", function(d) {
                                centroids[id_name_map[d.id].code] = path.centroid(d);
                            });

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

                createStatistic = function (key, statFunc) {
                    if (typeof statFunc !== "function") return console.error("No statistics function given");
                    if (visualisations[key]) return console.warn("visualisation exists");

                    data_dfd.done(function (groups) {
                        groups.forEach(function(group) {
                            group.stats = group.stats || {};
                            group.stats[key] = statFunc(group);
                        });
                    });

                    visualisations[key] = {
                        statFunc: statFunc
                    };
                },

                showStatistic = function (keys, toStringFunc) {
                    if (typeof toStringFunc !== "function") return console.error("no toString function given for tooltip");
                    keys.forEach(function (key) {
                        if (!visualisations[key]) return console.error("unknown visualization " + key);
                    });

                    data_dfd.done(function (groups) {

                        groups.forEach(function(group) {
                            var sum = 0;
                            keys.forEach(function (key) {
                                sum += group.stats[key];
                            });

                            group.mergedstats = sum/keys.length;
                        });

                        // compute maximum percentage over all states and set a gradient color range
                        var min = d3.min(groups, function(group) { return +group.mergedstats; }),
                            max = d3.max(groups, function(group) { return +group.mergedstats; }),
                            colorScale = d3.scale.linear()
                                .range(['white', 'darkred'])
                                .domain([min, max]);

                        groups.forEach(function(group) {
                            var $state = $("#"+group.key.toUpperCase());

                            // unbind all previous events
                            $state.unbind();

                            // color the state according to the stats
                            $state.css("fill", colorScale(group.mergedstats));

                            // shows tooltip on mouseover
                            $state.on("mouseover", function() {
                                var statecode = $(this).attr("id"),
                                    state = $(this).attr("state"),
                                    centroid = centroids[statecode],
                                    x = centroid[0]; // + target.position().left;
                                    y = centroid[1]; //+ target.position().top;

                                tooltip.html(toStringFunc(group, group.mergedstats))
                                    .style("left", x + "px")
                                    .style("top", y - 20 + "px");
                                tooltip.transition().duration(200).style("opacity", 1);
                            }).on("mouseout", function(d) {
                                tooltip.transition().duration(500).style("opacity", 0);
                            });

                            // State interaction with other graphs
                            $state.on("click", (function (s) {
                                return function(e) {
                                    console.log("clicked on", s.key);
                                }
                            }(group)));

                        });
                    });
                };

            // Initialize the map and data
            initialize();

            return {
                getStates: function () {

                },
                createStatistic: createStatistic,
                showStatistic: showStatistic
            };
        }(target, opts));
    };

    return {
        createMap: createMap
    };
}(jQuery, d3));<commit_msg>Changed nesting and allowed year filters<commit_after>var usmapvis = usmapvis || (function ($, d3, undefined) {
    /*
    * Default map settings
    */
    var defaults = {
        width: 1000,
        height: 600
    },
    /*
    * Creates Us Map for visualisation
    */
    createMap = function (target, opts) {
        return (function (target, opts) {
            // Set options
            opts = $.extend({}, defaults, opts);
            opts.radius = Math.min(opts.width, opts.height) / 3;

            // declare variables
            var visualisations = {},

                centroids = {},
                centered,

                projection = d3.geo.albersUsa()
                    .scale(opts.width)
                    .translate([opts.width / 2, opts.height / 2 + 20]),

                path = d3.geo.path()
                    .projection(projection),

                svg = target.append("svg")
                    .attr("width", opts.width)
                    .attr("height", opts.height),
                g = svg.append("g"),

                tooltip = d3.select("body")
                    .append("div")
                    .attr("class", "tooltip")
                    .style("opacity", 0),

                // Get us state data
                id_name_map = { 0: null },
                short_name_id_map = { 0: null },

                data_dfd = $.Deferred();

            var initialize = function () {
                    // get us state names and codes
                    d3.tsv("data/us-state-names.tsv", function(error, names) {
                        names.forEach(function (name) {
                            id_name_map[name.id] = name;
                            short_name_id_map[name.code] = name.id;
                        });
                    });

                    createUsMap();

                    d3.tsv("data/SPPA82-12-filtered.tsv", function(data) {
                        // groups all data by state
                        var groups = d3.nest()
                            .key(function(d) {return d.fips_state})
                            .key(function(d) {return d.year})
                            .entries(data);

                        // Set groupname
                        groups.forEach(function (group, i) {
                            group.name = id_name_map[short_name_id_map[group.key.toUpperCase()]].name;
                        });

                        data_dfd.resolve(groups);
                    });

                },

                createUsMap = function () {
                    // create visual map
                    d3.json("data/us.json", function(error, us) {
                        function clicked(d) {
                        }

                        g.append("g")
                            .attr("id", "states")
                            .selectAll("path")
                            .data(topojson.feature(us, us.objects.states).features)
                            .enter()
                            .append("g")
                            .attr("class","state-path")
                            .attr("state", function(d) {
                                return id_name_map[d.id].name;
                            })
                            .attr("id", function(d) {
                                return id_name_map[d.id].code;
                            });

                        svg.selectAll('.state-path')
                            .append("path")
                            .attr("d", path)
                            .attr("centroid", function(d) {
                                centroids[id_name_map[d.id].code] = path.centroid(d);
                            });

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

                createStatistic = function (key, statFunc) {
                    if (typeof statFunc !== "function") return console.error("No statistics function given");
                    if (visualisations[key]) return console.warn("visualisation exists");

                    data_dfd.done(function (groups) {
                        groups.forEach( function(state) {
                            state.values.forEach(function(year) {
                                year.stats = year.stats || {};
                                year.stats[key] = statFunc(year);
                            });
                        });
                    });

                    visualisations[key] = {
                        statFunc: statFunc
                    };
                },

                showStatistic = function (keys, years, toStringFunc) {
                    if (typeof toStringFunc !== "function") return console.error("no toString function given for tooltip");
                    keys.forEach(function (key) {
                        if (!visualisations[key]) return console.error("unknown visualization " + key);
                    });

                    data_dfd.done(function (groups) {

                    // aggregates the percentages for the selected types of cultural activities and selected years
                    groups.forEach(function(group) {
                        var sum = 0;
                        group.values.forEach(function(year) {
                            if(years.indexOf(year.key) != -1) {
                                keys.forEach(function (key) {
                                    sum += year.stats[key];
                                });
                                sum = sum/keys.length;
                            }
                        });
                        group.mergedstats = sum/years.length;
                    });

                    // compute maximum percentage over all states and set a gradient color range
                    var min = d3.min(groups, function(group) { return +group.mergedstats; }),
                        max = d3.max(groups, function(group) { return +group.mergedstats; }),
                        colorScale = d3.scale.linear()
                            .range(['white', 'darkred'])
                            .domain([min, max]);

                    groups.forEach(function(group) {
                        var $state = $("#"+group.key.toUpperCase());

                        // unbind all previous events
                        $state.unbind();

                        // color the state according to the stats
                        $state.css("fill", colorScale(group.mergedstats));

                        // shows tooltip on mouseover
                        $state.on("mouseover", function() {
                            var statecode = $(this).attr("id"),
                                state = $(this).attr("state"),
                                centroid = centroids[statecode],
                                x = centroid[0]; // + target.position().left;
                                y = centroid[1]; //+ target.position().top;

                            tooltip.html(toStringFunc(group, group.mergedstats))
                                .style("left", x + "px")
                                .style("top", y - 20 + "px");
                            tooltip.transition().duration(200).style("opacity", 1);
                        }).on("mouseout", function(d) {
                            tooltip.transition().duration(500).style("opacity", 0);
                        });

                        // State interaction with other graphs
                        $state.on("click", (function (s) {
                            return function(e) {
                                console.log("clicked on", s.key);
                            }
                        }(group)));

                    });
                    });
                };

            // Initialize the map and data
            initialize();

            return {
                getStates: function () {

                },
                createStatistic: createStatistic,
                showStatistic: showStatistic
            };
        }(target, opts));
    };

    return {
        createMap: createMap
    };
}(jQuery, d3));<|endoftext|>


<commit_before>var bson = require('bson');

/**
 * Map of all extended types to serializers (stringify) and deserializers (parse).
 *
 * @api private
 */
module.exports = {
  serialize: {
    ObjectID: function(v) {
      return {
        $oid: v.toString()
      };
    },
    Binary: function(v) {
      return {
        $binary: v.buffer.toString('base64'),
        $type: v.sub_type.toString(16)
      };
    },
    DBRef: function(v) {
      var id = typeof v.oid === 'object'
      && module.exports.serialize[v.oid.constructor.name] ? module.exports.serialize[v.oid.constructor.name](v.oid)
        : v.oid;
      return {
        $ref: v.namespace,
        $id: id
      };
    },
    Timestamp: function(v) {
      return {
        $timestamp: {
          t: v.low_,
          i: v.high_
        }
      };
    },
    Long: function(v) {
      return {
        $numberLong: v.toString()
      };
    },
    MaxKey: function() {
      return {
        $maxKey: 1
      };
    },
    MinKey: function() {
      return {
        $minKey: 1
      };
    },
    Date: function(v) {
      return {
        $date: v.toISOString()
      };
    },
    RegExp: function(v) {
      var o = '';

      if (v.global) {
        o += 'g';
      }
      if (v.ignoreCase) {
        o += 'i';
      }
      if (v.multiline) {
        o += 'm';
      }

      return {
        $regex: v.source,
        $options: o
      };
    },
    Undefined: function() {
      return {
        $undefined: true
      };
    }
  },
  /* eslint new-cap:0 */
  deserialize: {
    $oid: function(data) {
      return bson.ObjectID(data.$oid);
    },
    $binary: function(val) {
      return bson.Binary(new Buffer(val.$binary, 'base64'), parseInt(val.$type, 16));
    },
    $ref: function(val) {
      var id = typeof val.$id === 'object'
      && module.exports.deserialize[Object.keys(val.$id)[0]] ? module.exports.deserialize[Object.keys(val.$id)[0]](val.$id)
        : val.$id;
      return bson.DBRef(val.$ref, id);
    },
    $timestamp: function(val) {
      return bson.Timestamp(val.$timestamp.t, val.$timestamp.i);
    },
    $numberLong: function(val) {
      return bson.Long.fromString(val.$numberLong);
    },
    $maxKey: function() {
      return bson.MaxKey();
    },
    $minKey: function() {
      return bson.MinKey();
    },
    $date: function(val) {
      var d = new Date();

      // Kernel bug.  See #2 http://git.io/AEbmFg
      if (isNaN(d.setTime(val.$date))) {
        d = new Date(val.$date);
      }
      return d;
    },
    $regex: function(val) {
      return new RegExp(val.$regex, val.$options);
    },
    $undefined: function() {
      return undefined;
    }
  }
};
<commit_msg>explicitly call toHexString on ObjectId's<commit_after>var bson = require('bson');

/**
 * Map of all extended types to serializers (stringify) and deserializers (parse).
 *
 * @api private
 */
module.exports = {
  serialize: {
    ObjectID: function(v) {
      return {
        $oid: bson.ObjectID.prototype.toHexString.call(v)
      };
    },
    Binary: function(v) {
      return {
        $binary: v.buffer.toString('base64'),
        $type: v.sub_type.toString(16)
      };
    },
    DBRef: function(v) {
      var id = typeof v.oid === 'object'
      && module.exports.serialize[v.oid.constructor.name] ? module.exports.serialize[v.oid.constructor.name](v.oid)
        : v.oid;
      return {
        $ref: v.namespace,
        $id: id
      };
    },
    Timestamp: function(v) {
      return {
        $timestamp: {
          t: v.low_,
          i: v.high_
        }
      };
    },
    Long: function(v) {
      return {
        $numberLong: v.toString()
      };
    },
    MaxKey: function() {
      return {
        $maxKey: 1
      };
    },
    MinKey: function() {
      return {
        $minKey: 1
      };
    },
    Date: function(v) {
      return {
        $date: v.toISOString()
      };
    },
    RegExp: function(v) {
      var o = '';

      if (v.global) {
        o += 'g';
      }
      if (v.ignoreCase) {
        o += 'i';
      }
      if (v.multiline) {
        o += 'm';
      }

      return {
        $regex: v.source,
        $options: o
      };
    },
    Undefined: function() {
      return {
        $undefined: true
      };
    }
  },
  /* eslint new-cap:0 */
  deserialize: {
    $oid: function(data) {
      return bson.ObjectID(data.$oid);
    },
    $binary: function(val) {
      return bson.Binary(new Buffer(val.$binary, 'base64'), parseInt(val.$type, 16));
    },
    $ref: function(val) {
      var id = typeof val.$id === 'object'
      && module.exports.deserialize[Object.keys(val.$id)[0]] ? module.exports.deserialize[Object.keys(val.$id)[0]](val.$id)
        : val.$id;
      return bson.DBRef(val.$ref, id);
    },
    $timestamp: function(val) {
      return bson.Timestamp(val.$timestamp.t, val.$timestamp.i);
    },
    $numberLong: function(val) {
      return bson.Long.fromString(val.$numberLong);
    },
    $maxKey: function() {
      return bson.MaxKey();
    },
    $minKey: function() {
      return bson.MinKey();
    },
    $date: function(val) {
      var d = new Date();

      // Kernel bug.  See #2 http://git.io/AEbmFg
      if (isNaN(d.setTime(val.$date))) {
        d = new Date(val.$date);
      }
      return d;
    },
    $regex: function(val) {
      return new RegExp(val.$regex, val.$options);
    },
    $undefined: function() {
      return undefined;
    }
  }
};
<|endoftext|>


<commit_before>const check = require('./checksum');
module.exports = (message) => {
    let res = message.content.trim().substring(6);
    let algo = res.split(' ')[0];
    res = res.substring(algo.length + 1).trim();
    if (crypto.getHashes().indexOf(algo) === -1) {
        message.channel.sendMessage('Invalid algorithm \n Valid hashing Algorithms are:\n' + crypto.getHashes().join(' , '));
        return;
    }
    res = checksum(res, algo);
    console.log(res); message.channel.sendMessage('hash of message:' + res);
    if (message.attachments.size > 0) {
        res = message.attachments.first().url;
        request(res).then(body => message.channel.sendMessage('Hash of file:\n' + checksum(body, algo)));
    }
}<commit_msg>Fix hash<commit_after>const check = require('./checksum');
const crypto = require('crypto');
module.exports = (message) => {
    let res = message.content.trim().substring(6);
    let algo = res.split(' ')[0];
    res = res.substring(algo.length + 1).trim();
    if (crypto.getHashes().indexOf(algo) === -1) {
        message.channel.sendMessage('Invalid algorithm \n Valid hashing Algorithms are:\n' + crypto.getHashes().join(' , '));
        return;
    }
    res = checksum(res, algo);
    console.log(res); message.channel.sendMessage('hash of message:' + res);
    if (message.attachments.size > 0) {
        res = message.attachments.first().url;
        request(res).then(body => message.channel.sendMessage('Hash of file:\n' + checksum(body, algo)));
    }
}<|endoftext|>


<commit_before>"use strict";
var _ = {
  omit: require("lodash.omit")
};
var async = require("async");
var debug = require("./debugging");
var mongodb = require("mongodb");
var Joi = require("joi");

var MongoStore = module.exports = function MongoStore(config) {
  this._config = config;
};

var FILTER_OPERATORS = ["<", ">", "~", ":"];

/**
  Handlers readiness status. This should be set to `true` once all handlers are ready to process requests.
 */
MongoStore.prototype.ready = false;

MongoStore._mongoUuid = function(uuid) {
  return new mongodb.Binary(uuid, mongodb.Binary.SUBTYPE_UUID);
};

MongoStore._isRelationshipAttribute = function(attribute) {
  return attribute._settings && (attribute._settings.__one || attribute._settings.__many);
};

MongoStore._toMongoDocument = function(resource) {
  var document = _.omit(resource, function(value) { return value === undefined; });
  document._id = MongoStore._mongoUuid(document.id);
  return document;
};

MongoStore._getRelationshipAttributeNames = function(attributes) {
  var attributeNames = Object.getOwnPropertyNames(attributes);
  var relationshipAttributeNames = attributeNames.reduce(function(partialAttributeNames, name) {
    var attribute = attributes[name];
    if (MongoStore._isRelationshipAttribute(attribute)) {
      return partialAttributeNames.concat(name);
    }
    return partialAttributeNames;
  }, []);
  return relationshipAttributeNames;
};

MongoStore._splitFilterElement = function(filterElementStr) {
  if (FILTER_OPERATORS.indexOf(filterElementStr[0]) !== -1) {
    return { operator: filterElementStr[0], value: filterElementStr.substring(1) };
  }
  return { operator: null, value: filterElementStr };
};

MongoStore._filterElementToMongoExpr = function(attributeConfig, filterElementStr) {
  var filterElement = MongoStore._splitFilterElement(filterElementStr);
  var value = filterElement.value;
  if (!attributeConfig._settings) {  // not a relationship attribute
    var validationResult = attributeConfig.validate(filterElement.value);
    if (validationResult.error) return null;
    value = validationResult.value;
  }
  if (!filterElement.operator) return value;
  if (["~", ":"].indexOf(filterElement.operator) !== -1 && typeof value !== "string") {
    return null;
  }
  var mongoExpr = {
    ">": { $gt: value },
    "<": { $lt: value },
    "~": new RegExp("^" + value + "$", "i"),
    ":": new RegExp(value)
  }[filterElement.operator];
  return mongoExpr;
};

MongoStore.prototype._getSearchCriteria = function(request) {
  var self = this;
  if (!request.params.filter) return { };

  var criteria = Object.keys(request.params.filter).map(function(attribute) {
    var attributeConfig = self.resourceConfig.attributes[attribute];
    // If the filter attribute doesn't exist, skip it
    if (!attributeConfig) return null;

    var values = request.params.filter[attribute];
    // Relationships need to be queried via .id
    if (attributeConfig._settings) {
      attribute += ".id";
      // Filters on nested resources should be skipped
      if (values instanceof Object) return null;
    }

    values = [].concat(values); // Coerce values to an array to simplify the logic
    var filterElemForAttrToMongoExpr = MongoStore._filterElementToMongoExpr.bind(null, attributeConfig);
    values = values.map(filterElemForAttrToMongoExpr);
    values = values.reduce(function(mongoExpressions, mongoExpr) {
      if (mongoExpr !== null) {
        var mongoExprForAttr = { };
        mongoExprForAttr[attribute] = mongoExpr;
        mongoExpressions.push(mongoExprForAttr);
      }
      return mongoExpressions;
    }, []);
    if (values.length === 0) {
      return null;
    }
    if (values.length === 1) {
      return values[0];
    }
    return { $or: values };
  }).filter(function(value) {
    return value !== null;
  });
  if (criteria.length === 0) {
    return { };
  }
  if (criteria.length === 1) {
    return criteria[0];
  }
  return { $and: criteria };
};

MongoStore._notFoundError = function(type, id) {
  return {
    status: "404",
    code: "ENOTFOUND",
    title: "Requested resource does not exist",
    detail: "There is no " + type + " with id " + id
  };
};

MongoStore._unknownError = function(err) {
  return {
    status: "500",
    code: "EUNKNOWN",
    title: "An unknown error has occured",
    detail: err
  };
};

MongoStore.prototype._createIndexesForRelationships = function(collection, relationshipAttributeNames) {
  var index = relationshipAttributeNames.reduce(function(partialIndex, name) {
    partialIndex[name + ".id"] = 1;
    return partialIndex;
  }, {});

  if (Object.keys(index).length) {
    collection.createIndex(index);
  }
};

MongoStore.prototype._applySort = function(request, cursor) {
  if (!request.params.sort) return cursor;

  var attribute = request.params.sort;
  var order = 1;
  attribute = String(attribute);
  if (attribute[0] === "-") {
    order = -1;
    attribute = attribute.substring(1, attribute.length);
  }
  var sortParam = { };
  sortParam[attribute] = order;

  return cursor.sort(sortParam);
};

MongoStore.prototype._applyPagination = function(request, cursor) {
  if (!request.params.page) return cursor;

  return cursor.skip(request.params.page.offset).limit(request.params.page.limit);
};

/**
  Initialise gets invoked once for each resource that uses this handler.
 */
MongoStore.prototype.initialise = function(resourceConfig) {
  var self = this;
  if (!self._config.url) {
    return console.error("MongoDB url missing from configuration");
  }
  self.resourceConfig = resourceConfig;
  self.relationshipAttributeNames = MongoStore._getRelationshipAttributeNames(resourceConfig.attributes);
  mongodb.MongoClient.connect(self._config.url, {
    server: {
      reconnectTries: 999999999,
      reconnectInterval: 5000
    }
  }).then(function(db) {
    self._db = db;
    self._db.on("close", function(err) {
      console.error("mongodb connection closed:", err.message);
      self.ready = false;
      self._db.collection("Nope").findOne({ _id: 0 }, { _id: 0 }, function() {
        console.error("mongodb connection is back");
        self.ready = true;
      });
    });
  }).catch(function(err) {
    console.error("mongodb connection failed:", err.message);
    setTimeout(function() {
      self.initialise(resourceConfig);
    }, 5000);
  }).then(function() {
    var resourceName = resourceConfig.resource;
    var collection = self._db.collection(resourceName);
    self._createIndexesForRelationships(collection, self.relationshipAttributeNames);
    self.ready = true;
  });
};

/**
  Drops the database if it already exists and populates it with example documents.
 */
MongoStore.prototype.populate = function(callback) {
  var self = this;
  if (!self._db) return;

  self._db.dropDatabase(function(err) {
    if (err) return console.error("error dropping database", err.message);
    async.each(self.resourceConfig.examples, function(document, cb) {
      var validationResult = Joi.validate(document, self.resourceConfig.attributes);
      if (validationResult.error) {
        return cb(validationResult.error);
      }
      self.create({ params: {} }, validationResult.value, cb);
    }, function(error) {
      if (error) console.error("error creating example document:", error);
      return callback();
    });
  });
};

/**
  Search for a list of resources, give a resource type.
 */
MongoStore.prototype.search = function(request, callback) {
  var self = this;
  var collection = self._db.collection(request.params.type);
  var criteria = self._getSearchCriteria(request);
  debug("search", JSON.stringify(criteria));

  async.parallel({
    resultSet: function(asyncCallback) {
      var cursor = collection.find(criteria, { _id: 0 });
      self._applySort(request, cursor);
      self._applyPagination(request, cursor);
      return cursor.toArray(asyncCallback);
    },
    totalRows: function(asyncCallback) {
      return collection.find(criteria, { _id: 0 }).count(asyncCallback);
    }
  }, function(err, results) {
    if (err) {
      return callback(MongoStore._unknownError);
    }
    return callback(null, results.resultSet, results.totalRows);
  });
};

/**
  Find a specific resource, given a resource type and and id.
 */
MongoStore.prototype.find = function(request, callback) {
  var collection = this._db.collection(request.params.type);
  var documentId = MongoStore._mongoUuid(request.params.id);

  debug("findOne", JSON.stringify({ _id: documentId }));
  collection.findOne({ _id: documentId }, { _id: 0 }, function(err, result) {
    if (err || !result) {
      return callback(MongoStore._notFoundError(request.params.type, request.params.id));
    }
    return callback(null, result);
  });
};

/**
  Create (store) a new resource give a resource type and an object.
 */
MongoStore.prototype.create = function(request, newResource, callback) {
  var collection = this._db.collection(newResource.type);
  var document = MongoStore._toMongoDocument(newResource);
  debug("insert", JSON.stringify(document));
  collection.insertOne(document, function(err) {
    if (err) return callback(MongoStore._unknownError(err));
    collection.findOne(document, { _id: 0 }, callback);
  });
};

/**
  Delete a resource, given a resource type and an id.
 */
MongoStore.prototype.delete = function(request, callback) {
  var collection = this._db.collection(request.params.type);
  var documentId = MongoStore._mongoUuid(request.params.id);
  collection.deleteOne({ _id: documentId }, function(err, result) {
    if (err) return callback(MongoStore._unknownError(err));
    if (result.deletedCount === 0) {
      return callback(MongoStore._notFoundError(request.params.type, request.params.id));
    }
    return callback(null, result);
  });
};

/**
  Update a resource, given a resource type and id, along with a partialResource.
  partialResource contains a subset of changes that need to be merged over the original.
 */
MongoStore.prototype.update = function(request, partialResource, callback) {
  var collection = this._db.collection(request.params.type);
  var documentId = MongoStore._mongoUuid(request.params.id);
  var partialDocument = _.omit(partialResource, function(value) { return value === undefined; });
  debug("findOneAndUpdate", JSON.stringify(partialDocument));
  collection.findOneAndUpdate({
    _id: documentId
  }, {
    $set: partialDocument
  }, {
    returnOriginal: false,
    projection: { _id: 0 }
  }, function(err, result) {
    if (err) {
      debug("err", JSON.stringify(err));
      return callback(MongoStore._unknownError(err));
    }

    if (!result || !result.value) {
      return callback(MongoStore._notFoundError(request.params.type, request.params.id));
    }

    debug("result", JSON.stringify(result));
    return callback(null, result.value);
  });
};
<commit_msg>Implement "createIndex" via "ensureIndex"<commit_after>"use strict";
var _ = {
  omit: require("lodash.omit")
};
var async = require("async");
var debug = require("./debugging");
var mongodb = require("mongodb");
var Joi = require("joi");

var MongoStore = module.exports = function MongoStore(config) {
  this._config = config;
};

var FILTER_OPERATORS = ["<", ">", "~", ":"];

/**
  Handlers readiness status. This should be set to `true` once all handlers are ready to process requests.
 */
MongoStore.prototype.ready = false;

MongoStore._mongoUuid = function(uuid) {
  return new mongodb.Binary(uuid, mongodb.Binary.SUBTYPE_UUID);
};

MongoStore._isRelationshipAttribute = function(attribute) {
  return attribute._settings && (attribute._settings.__one || attribute._settings.__many);
};

MongoStore._toMongoDocument = function(resource) {
  var document = _.omit(resource, function(value) { return value === undefined; });
  document._id = MongoStore._mongoUuid(document.id);
  return document;
};

MongoStore._getRelationshipAttributeNames = function(attributes) {
  var attributeNames = Object.getOwnPropertyNames(attributes);
  var relationshipAttributeNames = attributeNames.reduce(function(partialAttributeNames, name) {
    var attribute = attributes[name];
    if (MongoStore._isRelationshipAttribute(attribute)) {
      return partialAttributeNames.concat(name);
    }
    return partialAttributeNames;
  }, []);
  return relationshipAttributeNames;
};

MongoStore._splitFilterElement = function(filterElementStr) {
  if (FILTER_OPERATORS.indexOf(filterElementStr[0]) !== -1) {
    return { operator: filterElementStr[0], value: filterElementStr.substring(1) };
  }
  return { operator: null, value: filterElementStr };
};

MongoStore._filterElementToMongoExpr = function(attributeConfig, filterElementStr) {
  var filterElement = MongoStore._splitFilterElement(filterElementStr);
  var value = filterElement.value;
  if (!attributeConfig._settings) {  // not a relationship attribute
    var validationResult = attributeConfig.validate(filterElement.value);
    if (validationResult.error) return null;
    value = validationResult.value;
  }
  if (!filterElement.operator) return value;
  if (["~", ":"].indexOf(filterElement.operator) !== -1 && typeof value !== "string") {
    return null;
  }
  var mongoExpr = {
    ">": { $gt: value },
    "<": { $lt: value },
    "~": new RegExp("^" + value + "$", "i"),
    ":": new RegExp(value)
  }[filterElement.operator];
  return mongoExpr;
};

MongoStore.prototype._getSearchCriteria = function(request) {
  var self = this;
  if (!request.params.filter) return { };

  var criteria = Object.keys(request.params.filter).map(function(attribute) {
    var attributeConfig = self.resourceConfig.attributes[attribute];
    // If the filter attribute doesn't exist, skip it
    if (!attributeConfig) return null;

    var values = request.params.filter[attribute];
    // Relationships need to be queried via .id
    if (attributeConfig._settings) {
      attribute += ".id";
      // Filters on nested resources should be skipped
      if (values instanceof Object) return null;
    }

    values = [].concat(values); // Coerce values to an array to simplify the logic
    var filterElemForAttrToMongoExpr = MongoStore._filterElementToMongoExpr.bind(null, attributeConfig);
    values = values.map(filterElemForAttrToMongoExpr);
    values = values.reduce(function(mongoExpressions, mongoExpr) {
      if (mongoExpr !== null) {
        var mongoExprForAttr = { };
        mongoExprForAttr[attribute] = mongoExpr;
        mongoExpressions.push(mongoExprForAttr);
      }
      return mongoExpressions;
    }, []);
    if (values.length === 0) {
      return null;
    }
    if (values.length === 1) {
      return values[0];
    }
    return { $or: values };
  }).filter(function(value) {
    return value !== null;
  });
  if (criteria.length === 0) {
    return { };
  }
  if (criteria.length === 1) {
    return criteria[0];
  }
  return { $and: criteria };
};

MongoStore._notFoundError = function(type, id) {
  return {
    status: "404",
    code: "ENOTFOUND",
    title: "Requested resource does not exist",
    detail: "There is no " + type + " with id " + id
  };
};

MongoStore._unknownError = function(err) {
  return {
    status: "500",
    code: "EUNKNOWN",
    title: "An unknown error has occured",
    detail: err
  };
};

MongoStore.prototype._createIndexesForRelationships = function(collection, relationshipAttributeNames) {
  if (!(relationshipAttributeNames instanceof Array) || !relationshipAttributeNames.length) { return }

  var index = relationshipAttributeNames.reduce(function(partialIndex, name) {
    if (name) {
      partialIndex.push([name + ".id", 1]);
    }

    return partialIndex;
  }, []);

  collection.ensureIndex(index);
};

MongoStore.prototype._applySort = function(request, cursor) {
  if (!request.params.sort) return cursor;

  var attribute = request.params.sort;
  var order = 1;
  attribute = String(attribute);
  if (attribute[0] === "-") {
    order = -1;
    attribute = attribute.substring(1, attribute.length);
  }
  var sortParam = { };
  sortParam[attribute] = order;

  return cursor.sort(sortParam);
};

MongoStore.prototype._applyPagination = function(request, cursor) {
  if (!request.params.page) return cursor;

  return cursor.skip(request.params.page.offset).limit(request.params.page.limit);
};

/**
  Initialise gets invoked once for each resource that uses this handler.
 */
MongoStore.prototype.initialise = function(resourceConfig) {
  var self = this;
  if (!self._config.url) {
    return console.error("MongoDB url missing from configuration");
  }
  self.resourceConfig = resourceConfig;
  self.relationshipAttributeNames = MongoStore._getRelationshipAttributeNames(resourceConfig.attributes);
  mongodb.MongoClient.connect(self._config.url, {
    server: {
      reconnectTries: 999999999,
      reconnectInterval: 5000
    }
  }).then(function(db) {
    self._db = db;
    self._db.on("close", function(err) {
      console.error("mongodb connection closed:", err.message);
      self.ready = false;
      self._db.collection("Nope").findOne({ _id: 0 }, { _id: 0 }, function() {
        console.error("mongodb connection is back");
        self.ready = true;
      });
    });
  }).catch(function(err) {
    console.error("mongodb connection failed:", err.message);
    setTimeout(function() {
      self.initialise(resourceConfig);
    }, 5000);
  }).then(function() {
    var resourceName = resourceConfig.resource;
    var collection = self._db.collection(resourceName);
    self._createIndexesForRelationships(collection, self.relationshipAttributeNames);
    self.ready = true;
  });
};

/**
  Drops the database if it already exists and populates it with example documents.
 */
MongoStore.prototype.populate = function(callback) {
  var self = this;
  if (!self._db) return;

  self._db.dropDatabase(function(err) {
    if (err) return console.error("error dropping database", err.message);
    async.each(self.resourceConfig.examples, function(document, cb) {
      var validationResult = Joi.validate(document, self.resourceConfig.attributes);
      if (validationResult.error) {
        return cb(validationResult.error);
      }
      self.create({ params: {} }, validationResult.value, cb);
    }, function(error) {
      if (error) console.error("error creating example document:", error);
      return callback();
    });
  });
};

/**
  Search for a list of resources, give a resource type.
 */
MongoStore.prototype.search = function(request, callback) {
  var self = this;
  var collection = self._db.collection(request.params.type);
  var criteria = self._getSearchCriteria(request);
  debug("search", JSON.stringify(criteria));

  async.parallel({
    resultSet: function(asyncCallback) {
      var cursor = collection.find(criteria, { _id: 0 });
      self._applySort(request, cursor);
      self._applyPagination(request, cursor);
      return cursor.toArray(asyncCallback);
    },
    totalRows: function(asyncCallback) {
      return collection.find(criteria, { _id: 0 }).count(asyncCallback);
    }
  }, function(err, results) {
    if (err) {
      return callback(MongoStore._unknownError);
    }
    return callback(null, results.resultSet, results.totalRows);
  });
};

/**
  Find a specific resource, given a resource type and and id.
 */
MongoStore.prototype.find = function(request, callback) {
  var collection = this._db.collection(request.params.type);
  var documentId = MongoStore._mongoUuid(request.params.id);

  debug("findOne", JSON.stringify({ _id: documentId }));
  collection.findOne({ _id: documentId }, { _id: 0 }, function(err, result) {
    if (err || !result) {
      return callback(MongoStore._notFoundError(request.params.type, request.params.id));
    }
    return callback(null, result);
  });
};

/**
  Create (store) a new resource give a resource type and an object.
 */
MongoStore.prototype.create = function(request, newResource, callback) {
  var collection = this._db.collection(newResource.type);
  var document = MongoStore._toMongoDocument(newResource);
  debug("insert", JSON.stringify(document));
  collection.insertOne(document, function(err) {
    if (err) return callback(MongoStore._unknownError(err));
    collection.findOne(document, { _id: 0 }, callback);
  });
};

/**
  Delete a resource, given a resource type and an id.
 */
MongoStore.prototype.delete = function(request, callback) {
  var collection = this._db.collection(request.params.type);
  var documentId = MongoStore._mongoUuid(request.params.id);
  collection.deleteOne({ _id: documentId }, function(err, result) {
    if (err) return callback(MongoStore._unknownError(err));
    if (result.deletedCount === 0) {
      return callback(MongoStore._notFoundError(request.params.type, request.params.id));
    }
    return callback(null, result);
  });
};

/**
  Update a resource, given a resource type and id, along with a partialResource.
  partialResource contains a subset of changes that need to be merged over the original.
 */
MongoStore.prototype.update = function(request, partialResource, callback) {
  var collection = this._db.collection(request.params.type);
  var documentId = MongoStore._mongoUuid(request.params.id);
  var partialDocument = _.omit(partialResource, function(value) { return value === undefined; });
  debug("findOneAndUpdate", JSON.stringify(partialDocument));
  collection.findOneAndUpdate({
    _id: documentId
  }, {
    $set: partialDocument
  }, {
    returnOriginal: false,
    projection: { _id: 0 }
  }, function(err, result) {
    if (err) {
      debug("err", JSON.stringify(err));
      return callback(MongoStore._unknownError(err));
    }

    if (!result || !result.value) {
      return callback(MongoStore._notFoundError(request.params.type, request.params.id));
    }

    debug("result", JSON.stringify(result));
    return callback(null, result.value);
  });
};
<|endoftext|>


<commit_before>module.exports = function detectBrowser(userAgentString) {
  var browsers = [
    [ 'edge', /Edge\/([0-9\._]+)/ ],
    [ 'yandexbrowser', /YaBrowser\/([0-9\._]+)/ ],
    [ 'chrome', /(?!Chrom.*OPR)Chrom(?:e|ium)\/([0-9\.]+)(:?\s|$)/ ],
    [ 'crios', /CriOS\/([0-9\.]+)(:?\s|$)/ ],
    [ 'firefox', /Firefox\/([0-9\.]+)(?:\s|$)/ ],
    [ 'opera', /Opera\/([0-9\.]+)(?:\s|$)/ ],
    [ 'opera', /OPR\/([0-9\.]+)(:?\s|$)$/ ],
    [ 'ie', /Trident\/7\.0.*rv\:([0-9\.]+)\).*Gecko$/ ],
    [ 'ie', /MSIE\s([0-9\.]+);.*Trident\/[4-7].0/ ],
    [ 'ie', /MSIE\s(7\.0)/ ],
    [ 'bb10', /BB10;\sTouch.*Version\/([0-9\.]+)/ ],
    [ 'android', /Android\s([0-9\.]+)/ ],
    [ 'mobile-safari', /Version\/([0-9\._]+).*Mobile.*Safari.*/ ],
    [ 'safari', /Version\/([0-9\._]+).*Safari/ ]
  ];

  return browsers.map(function (rule) {
      if (rule[1].test(userAgentString)) {
          var match = rule[1].exec(userAgentString);

          return {
              name: rule[0],
              version: match && match[1].split(/[._]/).slice(0,3).join('-')
          };
      }
  }).filter(Boolean).shift();
};
<commit_msg>Update detectBrowser.js<commit_after>module.exports = function detectBrowser(userAgentString) {
  var browsers = [
    [ 'edge', /Edge\/([0-9\._]+)/ ],
    [ 'yandexbrowser', /YaBrowser\/([0-9\._]+)/ ],
    [ 'chrome', /(?!Chrom.*OPR)Chrom(?:e|ium)\/([0-9\.]+)(:?\s|$)/ ],
    [ 'crios', /CriOS\/([0-9\.]+)(:?\s|$)/ ],
    [ 'firefox', /Firefox\/([0-9\.]+)(?:\s|$)/ ],
    [ 'opera', /Opera\/([0-9\.]+)(?:\s|$)/ ],
    [ 'opera', /OPR\/([0-9\.]+)(:?\s|$)$/ ],
    [ 'ie', /Trident\/7\.0.*rv\:([0-9\.]+)\).*Gecko$/ ],
    [ 'ie', /MSIE\s([0-9\.]+);.*Trident\/[4-7].0/ ],
    [ 'ie', /MSIE\s(7\.0)/ ],
    [ 'bb10', /BB10;\sTouch.*Version\/([0-9\.]+)/ ],
    [ 'android', /Android\s([0-9\.]+)/ ],
    [ 'mobile-safari', /Version\/([0-9\._]+).*Mobile.*Safari.*/ ],
    [ 'safari', /Version\/([0-9\._]+).*Safari/ ]
  ];

  return browsers.map(function (rule) {
      if (rule[1].test(userAgentString)) {
          var match = rule[1].exec(userAgentString);

          return {
              name: rule[0],
              version: match && match[1].split(/[._]/).slice(0,3).join('.')
          };
      }
  }).filter(Boolean).shift();
};
<|endoftext|>