<commit_before>'use strict';

var TurboCartoError = require('../../helper/turbo-carto-error');
var postcss = require('postcss');

function RampResult (values, filters, mapping) {
  this.values = values;
  this.filters = filters;
  this.mapping = mapping || '>';
}

module.exports = RampResult;

var STRATEGIES_SUPPORTED = {
  /**
   * `equality` will get as many values - 1, and will filter `column` with those filters,
   * last value will be used as default value.
   * Example:
   *  ```css
   *  marker-fill: ramp([cat_column], (red, green, blue, black), (1, 2, 3), ==);
   *  ```
   *
   * will generate:
   *  ```css
   *  marker-width: black;
   *  [cat_column = 1] {
   *    marker-width: red;
   *  }
   *  [cat_column = 2] {
   *    marker-width: green;
   *  }
   *  [cat_column = 3] {
   *    marker-width: blue;
   *  }
   *  ```
   *
   * This is useful for category ramps.
   * This works for numeric and string filters.
   */
  '=': 'equality',
  '==': 'equality',

  /**
   * `greater_than` and `greater_than_or_equal` will use first value as default value, and will break by first filter.
   * Example:
   *  ```css
   *  marker-width: ramp([price], (4, 8, 16, 32), (100, 200, 500, 600), >);
   *  ```
   *
   * Will generate:
   *  ```css
   *  marker-width: 4;
   *  [price > 100] {
   *    marker-width: 8;
   *  }
   *  [price > 200] {
   *    marker-width: 16;
   *  }
   *  [price > 500] {
   *    marker-width: 32;
   *  }
   *  ```
   *
   *
   *
   * This is useful for quantification methods like jenks, quantiles, and equal intervals.
   * This only work for numeric filters, otherwise it will throw an error.
   */
  '>': 'greater_than_or_equal',
  '>=': 'greater_than_or_equal',

  /**
   * Example:
   *  ```css
   *  marker-width: ramp([price], (4, 8, 16, 32), (50, 75.5, 88, 94.5), <);
   *  ```
   *
   * Will generate:
   *  ```css
   *  marker-width: 32;
   *  [price < 50] {
   *    marker-width: 4;
   *  }
   *  [price < 75.5] {
   *    marker-width: 8;
   *  }
   *  [price < 88] {
   *    marker-width: 16;
   *  }
   *  ```
   *
   * This is useful for quantification methods like headtails.
   * This only work for numeric filters, otherwise it will throw an error.
   */
  '<': 'less_than_or_equal',
  '<=': 'less_than_or_equal'

  /**
   * Future mappings
   * '!=': 'inequality',
   * 'in': 'set_inclusion',
   * '!in': 'set_exclusion',
   */
};

RampResult.prototype.process = function (column, decl) {
  var strategy = STRATEGIES_SUPPORTED[this.mapping];
  if (strategy === STRATEGIES_SUPPORTED['<']) {
    return this.processLessThanOrEqual(column, decl);
  } else if (strategy === STRATEGIES_SUPPORTED['==']) {
    return this.processEquality(column, decl);
  } else {
    return this.processGreaterThanOrEqual(column, decl);
  }
};

RampResult.supports = function (strategy) {
  return STRATEGIES_SUPPORTED.hasOwnProperty(strategy) || !strategy;
};

RampResult.prototype.processEquality = function (column, decl) {
  if ((this.filters.getLength()) > this.values.getMaxSize()) {
    throw new TurboCartoError('`' + this.mapping + '` requires more or same values than filters to work.');
  }

  var values = this.values.get(this.filters.getLength() + 1);
  var filters = this.filters.get();

  var initialDecl = decl;
  if (values.length !== filters.length) {
    var defaultValue = values[values.length - 1];
    initialDecl = postcss.decl({ prop: decl.prop, value: defaultValue });
    decl.replaceWith(initialDecl);
  }

  var previousNode = initialDecl;
  filters.forEach(function (filter, index) {
    var filterSelector = Number.isFinite(filter) ? filter : '"' + filter + '"';
    var rule = postcss.rule({
      selector: '[ ' + column + ' = ' + filterSelector + ' ]'
    });
    rule.append(postcss.decl({ prop: decl.prop, value: values[index] }));

    rule.moveAfter(previousNode);
    previousNode = rule;
  });

  if (values.length === filters.length) {
    decl.remove();
  }

  return { values: values, filters: filters, mapping: this.mapping };
};

RampResult.prototype.processGreaterThanOrEqual = function (column, decl) {
  var buckets = Math.min(this.values.getMaxSize(), this.filters.getMaxSize());

  var values = this.values.get(buckets + 1);
  var filters = this.filters.get(buckets);

  var defaultValue = values[0];
  var initialDecl = postcss.decl({ prop: decl.prop, value: defaultValue });
  decl.replaceWith(initialDecl);<commit_msg>Fix buckets = 1 use case<commit_after>'use strict';

var TurboCartoError = require('../../helper/turbo-carto-error');
var postcss = require('postcss');

function RampResult (values, filters, mapping) {
  this.values = values;
  this.filters = filters;
  this.mapping = mapping || '>';
}

module.exports = RampResult;

var STRATEGIES_SUPPORTED = {
  /**
   * `equality` will get as many values - 1, and will filter `column` with those filters,
   * last value will be used as default value.
   * Example:
   *  ```css
   *  marker-fill: ramp([cat_column], (red, green, blue, black), (1, 2, 3), ==);
   *  ```
   *
   * will generate:
   *  ```css
   *  marker-width: black;
   *  [cat_column = 1] {
   *    marker-width: red;
   *  }
   *  [cat_column = 2] {
   *    marker-width: green;
   *  }
   *  [cat_column = 3] {
   *    marker-width: blue;
   *  }
   *  ```
   *
   * This is useful for category ramps.
   * This works for numeric and string filters.
   */
  '=': 'equality',
  '==': 'equality',

  /**
   * `greater_than` and `greater_than_or_equal` will use first value as default value, and will break by first filter.
   * Example:
   *  ```css
   *  marker-width: ramp([price], (4, 8, 16, 32), (100, 200, 500, 600), >);
   *  ```
   *
   * Will generate:
   *  ```css
   *  marker-width: 4;
   *  [price > 100] {
   *    marker-width: 8;
   *  }
   *  [price > 200] {
   *    marker-width: 16;
   *  }
   *  [price > 500] {
   *    marker-width: 32;
   *  }
   *  ```
   *
   *
   *
   * This is useful for quantification methods like jenks, quantiles, and equal intervals.
   * This only work for numeric filters, otherwise it will throw an error.
   */
  '>': 'greater_than_or_equal',
  '>=': 'greater_than_or_equal',

  /**
   * Example:
   *  ```css
   *  marker-width: ramp([price], (4, 8, 16, 32), (50, 75.5, 88, 94.5), <);
   *  ```
   *
   * Will generate:
   *  ```css
   *  marker-width: 32;
   *  [price < 50] {
   *    marker-width: 4;
   *  }
   *  [price < 75.5] {
   *    marker-width: 8;
   *  }
   *  [price < 88] {
   *    marker-width: 16;
   *  }
   *  ```
   *
   * This is useful for quantification methods like headtails.
   * This only work for numeric filters, otherwise it will throw an error.
   */
  '<': 'less_than_or_equal',
  '<=': 'less_than_or_equal'

  /**
   * Future mappings
   * '!=': 'inequality',
   * 'in': 'set_inclusion',
   * '!in': 'set_exclusion',
   */
};

RampResult.prototype.process = function (column, decl) {
  var strategy = STRATEGIES_SUPPORTED[this.mapping];
  if (strategy === STRATEGIES_SUPPORTED['<']) {
    return this.processLessThanOrEqual(column, decl);
  } else if (strategy === STRATEGIES_SUPPORTED['==']) {
    return this.processEquality(column, decl);
  } else {
    return this.processGreaterThanOrEqual(column, decl);
  }
};

RampResult.supports = function (strategy) {
  return STRATEGIES_SUPPORTED.hasOwnProperty(strategy) || !strategy;
};

RampResult.prototype.processEquality = function (column, decl) {
  if ((this.filters.getLength()) > this.values.getMaxSize()) {
    throw new TurboCartoError('`' + this.mapping + '` requires more or same values than filters to work.');
  }

  var values = this.values.get(this.filters.getLength() + 1);
  var filters = this.filters.get();

  var initialDecl = decl;
  if (values.length !== filters.length) {
    var defaultValue = values[values.length - 1];
    initialDecl = postcss.decl({ prop: decl.prop, value: defaultValue });
    decl.replaceWith(initialDecl);
  }

  var previousNode = initialDecl;
  filters.forEach(function (filter, index) {
    var filterSelector = Number.isFinite(filter) ? filter : '"' + filter + '"';
    var rule = postcss.rule({
      selector: '[ ' + column + ' = ' + filterSelector + ' ]'
    });
    rule.append(postcss.decl({ prop: decl.prop, value: values[index] }));

    rule.moveAfter(previousNode);
    previousNode = rule;
  });

  if (values.length === filters.length) {
    decl.remove();
  }

  return { values: values, filters: filters, mapping: this.mapping };
};

RampResult.prototype.processGreaterThanOrEqual = function (column, decl) {
  var buckets = Math.min(this.values.getMaxSize(), this.filters.getMaxSize());

  var values = this.values.get((buckets <= 1) ? buckets + 1 : buckets);
  var filters = this.filters.get(buckets);

  var defaultValue = values[0];
  var initialDecl = postcss.decl({ prop: decl.prop, value: defaultValue });
  decl.replaceWith(initialDecl);
{'fraction_non_alphanumeric': 0.1640325129826146, 'fraction_numerical': 0.0167080605102732, 'mean_word_length': 2.9549107142857145, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 19, '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': '2949542', 'n_tokens_mistral': 3224, 'n_tokens_neox': 3042, 'n_words': 712}