<commit_before>/* eslint-disable func-style */
/* eslint-disable no-use-before-define */
import { flatten, includes, isPlainObject, sortedUniq, isFunction } from "lodash";
import Data from "./data";
import Scale from "./scale";
import Helpers from "./helpers";
import Collection from "./collection";

// Private Methods

function cleanDomain(domain, props, axis) {
  const scaleType = Scale.getScaleType(props, axis);

  if (scaleType !== "log") {
    return domain;
  }

  const rules = (dom) => {
    const almostZero = dom[0] < 0 || dom[1] < 0 ? -1 / Number.MAX_SAFE_INTEGER
    : 1 / Number.MAX_SAFE_INTEGER;
    const domainOne = dom[0] === 0 ? almostZero : dom[0];
    const domainTwo = dom[1] === 0 ? almostZero : dom[1];
    return [domainOne, domainTwo];
  };

  return rules(domain);
}

function getCumulativeData(props, axis, datasets) {
  const currentAxis = Helpers.getCurrentAxis(axis, props.horizontal);
  const otherAxis = currentAxis === "x" ? "y" : "x";
  const categories = [];
  const axisValues = [];
  datasets.forEach((dataset) => {
    dataset.forEach((data) => {
      if (data.category !== undefined && !includes(categories, data.category)) {
        categories.push(data.category);
      } else if (!includes(axisValues, data[`_${otherAxis}`])) {
        axisValues.push(data[`_${otherAxis}`]);
      }
    });
  });

  const _dataByCategory = () => {
    return categories.map((value) => {
      return datasets.reduce((prev, data) => {
        return data.category === value ? prev.concat(data[`_${axis}`]) : prev;
      }, []);
    });
  };

  const _dataByIndex = () => {
    return axisValues.map((value, index) => {
      return datasets.map((data) => data[index] && data[index][`_${currentAxis}`]);
    });
  };
  return categories.length === 0 ? _dataByIndex() : _dataByCategory();
}

function getDomainPadding(props, axis) {
  const formatPadding = (padding) => {
    return Array.isArray(padding) ?
      { left: padding[0], right: padding[1] } : { left: padding, right: padding };
  };

  return isPlainObject(props.domainPadding) ?
    formatPadding(props.domainPadding[axis]) : formatPadding(props.domainPadding);
}

function getFlatData(dataset, axis) {
  return flatten(dataset).map((datum) => {
    return datum[`_${axis}`] && datum[`_${axis}`][1] !== undefined ?
      datum[`_${axis}`][1] : datum[`_${axis}`];
  });
}

function getMaxFromData(dataset, axis) {
  let containsDate = false;
  const minValue = flatten(dataset).reduce((memo, datum) => {
    const current = datum[`_${axis}`] && datum[`_${axis}1`] !== undefined ?
      datum[`_${axis}1`] : datum[`_${axis}`];
    containsDate = containsDate || current instanceof Date;
    return memo > current ? memo : current;
  }, -Infinity);
  return containsDate ? new Date(minValue) : minValue;
}

function getMinFromData(dataset, axis) {
  let containsDate = false;
  const minValue = flatten(dataset).reduce((memo, datum) => {
    const current = datum[`_${axis}`] && datum[`_${axis}0`] !== undefined ?
      datum[`_${axis}0`] : datum[`_${axis}`];
    containsDate = containsDate || current instanceof Date;
    return memo < current ? memo : current;
  }, Infinity);
  return containsDate ? new Date(minValue) : minValue;
}

//eslint-disable-next-line max-statements
function padDomain(domain, props, axis) {
  if (!props.domainPadding) {
    return domain;
  }
  const minDomain = getMinFromProps(props, axis);
  const maxDomain = getMaxFromProps(props, axis);
  const padding = getDomainPadding(props, axis);
  if (!padding.left && !padding.right) {
    return domain;
  }

  const min = Collection.getMinValue(domain);
  const max = Collection.getMaxValue(domain);
  const range = Helpers.getRange(props, axis);
  const rangeExtent = Math.abs(range[0] - range[1]);

  // Naive initial padding calculation
  const initialPadding = {
    left: Math.abs(max - min) * padding.left / rangeExtent,
    right: Math.abs(max - min) * padding.right / rangeExtent
  };

  // Adjust the domain by the initial padding
  const adjustedDomain = {
    min: (min >= 0 && (min - initialPadding.left) <= 0) ? 0 : min.valueOf() - initialPadding.left,
    max: (max <= 0 && (max + initialPadding.right) >= 0) ? 0 : max.valueOf() + initialPadding.right
  };

  // re-calculate padding, taking the adjusted domain into account
  const finalPadding = {
    left: Math.abs(adjustedDomain.max - adjustedDomain.min) * padding.left / rangeExtent,
    right: Math.abs(adjustedDomain.max - adjustedDomain.min) * padding.right / rangeExtent
  };

  // Adjust the domain by the final padding
  const paddedDomain = {
    min: (min >= 0 && (min - finalPadding.left) <= 0) ? 0 : min.valueOf() - finalPadding.left,
    max: (max >= 0 && (max + finalPadding.right) <= 0) ? 0 : max.valueOf() + finalPadding.right
  };

  // default to minDomain / maxDomain if they exist
  const finalDomain = {
    min: minDomain !== undefined ? minDomain : paddedDomain.min,
    max: maxDomain !== undefined ? maxDomain : paddedDomain.max
  };

  return min instanceof Date || max instanceof Date ?
    getDomainFromMinMax(new Date(finalDomain.min), new Date(finalDomain.max)) :
    getDomainFromMinMax(finalDomain.min, finalDomain.max);
}

// Public Methods

/**
 * Returns a getDomain function
 * @param {Function} getDomainFromDataFunction: a function that takes props and axis and
 * returns a domain based on data
 * @param {Function} formatDomainFunction: a function that takes domain, props, and axis and
 * returns a formatted domain
 * @returns {Function} a function that takes props and axis and returns a formatted domain
 */
function createDomainFunction(getDomainFromDataFunction, formatDomainFunction) {
  getDomainFromDataFunction = isFunction(getDomainFromDataFunction) ?
    getDomainFromDataFunction : getDomainFromData;
  formatDomainFunction = isFunction(formatDomainFunction) ?
    formatDomainFunction : formatDomain;
  return (props, axis) => {
    const propsDomain = getDomainFromProps(props, axis);
    if (propsDomain) {<commit_msg>coerce domainPadding unless singleQuadrantDomainPadding prop is false<commit_after>/* eslint-disable func-style */
/* eslint-disable no-use-before-define */
import { flatten, includes, isPlainObject, sortedUniq, isFunction } from "lodash";
import Data from "./data";
import Scale from "./scale";
import Helpers from "./helpers";
import Collection from "./collection";

// Private Methods

function cleanDomain(domain, props, axis) {
  const scaleType = Scale.getScaleType(props, axis);

  if (scaleType !== "log") {
    return domain;
  }

  const rules = (dom) => {
    const almostZero = dom[0] < 0 || dom[1] < 0 ? -1 / Number.MAX_SAFE_INTEGER
    : 1 / Number.MAX_SAFE_INTEGER;
    const domainOne = dom[0] === 0 ? almostZero : dom[0];
    const domainTwo = dom[1] === 0 ? almostZero : dom[1];
    return [domainOne, domainTwo];
  };

  return rules(domain);
}

function getCumulativeData(props, axis, datasets) {
  const currentAxis = Helpers.getCurrentAxis(axis, props.horizontal);
  const otherAxis = currentAxis === "x" ? "y" : "x";
  const categories = [];
  const axisValues = [];
  datasets.forEach((dataset) => {
    dataset.forEach((data) => {
      if (data.category !== undefined && !includes(categories, data.category)) {
        categories.push(data.category);
      } else if (!includes(axisValues, data[`_${otherAxis}`])) {
        axisValues.push(data[`_${otherAxis}`]);
      }
    });
  });

  const _dataByCategory = () => {
    return categories.map((value) => {
      return datasets.reduce((prev, data) => {
        return data.category === value ? prev.concat(data[`_${axis}`]) : prev;
      }, []);
    });
  };

  const _dataByIndex = () => {
    return axisValues.map((value, index) => {
      return datasets.map((data) => data[index] && data[index][`_${currentAxis}`]);
    });
  };
  return categories.length === 0 ? _dataByIndex() : _dataByCategory();
}

function getDomainPadding(props, axis) {
  const formatPadding = (padding) => {
    return Array.isArray(padding) ?
      { left: padding[0], right: padding[1] } : { left: padding, right: padding };
  };

  return isPlainObject(props.domainPadding) ?
    formatPadding(props.domainPadding[axis]) : formatPadding(props.domainPadding);
}

function getFlatData(dataset, axis) {
  return flatten(dataset).map((datum) => {
    return datum[`_${axis}`] && datum[`_${axis}`][1] !== undefined ?
      datum[`_${axis}`][1] : datum[`_${axis}`];
  });
}

function getMaxFromData(dataset, axis) {
  let containsDate = false;
  const minValue = flatten(dataset).reduce((memo, datum) => {
    const current = datum[`_${axis}`] && datum[`_${axis}1`] !== undefined ?
      datum[`_${axis}1`] : datum[`_${axis}`];
    containsDate = containsDate || current instanceof Date;
    return memo > current ? memo : current;
  }, -Infinity);
  return containsDate ? new Date(minValue) : minValue;
}

function getMinFromData(dataset, axis) {
  let containsDate = false;
  const minValue = flatten(dataset).reduce((memo, datum) => {
    const current = datum[`_${axis}`] && datum[`_${axis}0`] !== undefined ?
      datum[`_${axis}0`] : datum[`_${axis}`];
    containsDate = containsDate || current instanceof Date;
    return memo < current ? memo : current;
  }, Infinity);
  return containsDate ? new Date(minValue) : minValue;
}

//eslint-disable-next-line max-statements
function padDomain(domain, props, axis) {
  if (!props.domainPadding) {
    return domain;
  }

  const minDomain = getMinFromProps(props, axis);
  const maxDomain = getMaxFromProps(props, axis);
  const padding = getDomainPadding(props, axis);
  if (!padding.left && !padding.right) {
    return domain;
  }

  const min = Collection.getMinValue(domain);
  const max = Collection.getMaxValue(domain);
  const range = Helpers.getRange(props, axis);
  const rangeExtent = Math.abs(range[0] - range[1]);

  // Naive initial padding calculation
  const initialPadding = {
    left: Math.abs(max - min) * padding.left / rangeExtent,
    right: Math.abs(max - min) * padding.right / rangeExtent
  };

  const singleQuadrantDomainPadding = isPlainObject(props.singleQuadrantDomainPadding) ?
    props.singleQuadrantDomainPadding[axis] : props.singleQuadrantDomainPadding;
  const adjust = (val, type) => {
    if (singleQuadrantDomainPadding === false) {
      return val;
    }
    const coerce = (type === "min" && min >= 0 && val <= 0) ||
      (type === "max" && max <= 0 && val >= 0);
    return coerce ? 0 : val;
  };

  // Adjust the domain by the initial padding
  const adjustedDomain = {
    min: adjust(min.valueOf() - initialPadding.left),
    max: adjust(max.valueOf() + initialPadding.right)
  };

  // re-calculate padding, taking the adjusted domain into account
  const finalPadding = {
    left: Math.abs(adjustedDomain.max - adjustedDomain.min) * padding.left / rangeExtent,
    right: Math.abs(adjustedDomain.max - adjustedDomain.min) * padding.right / rangeExtent
  };

  // Adjust the domain by the final padding
  const paddedDomain = {
    min: adjust(min.valueOf() - finalPadding.left),
    max: adjust(max.valueOf() + finalPadding.right)
  };

  // default to minDomain / maxDomain if they exist
  const finalDomain = {
    min: minDomain !== undefined ? minDomain : paddedDomain.min,
    max: maxDomain !== undefined ? maxDomain : paddedDomain.max
  };

  return min instanceof Date || max instanceof Date ?
    getDomainFromMinMax(new Date(finalDomain.min), new Date(finalDomain.max)) :
    getDomainFromMinMax(finalDomain.min, finalDomain.max);
}

// Public Methods

/**
 * Returns a getDomain function
 * @param {Function} getDomainFromDataFunction: a function that takes props and axis and
 * returns a domain based on data
 * @param {Function} formatDomainFunction: a function that takes domain, props, and axis and
 * returns a formatted domain
 * @returns {Function} a function that takes props and axis and returns a formatted domain
 */
function createDomainFunction(getDomainFromDataFunction, formatDomainFunction) {
  getDomainFromDataFunction = isFunction(getDomainFromDataFunction) ?
    getDomainFromDataFunction : getDomainFromData;
  formatDomainFunction = isFunction(formatDomainFunction) ?
    formatDomainFunction : formatDomain;
  return (props, axis) => {
    const propsDomain = getDomainFromProps(props, axis);
    if (propsDomain) {
{'fraction_non_alphanumeric': 0.14530261236410838, 'fraction_numerical': 0.005111147168586727, 'mean_word_length': 3.9308, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3486040', 'n_tokens_mistral': 3812, 'n_tokens_neox': 3759, 'n_words': 942}