<commit_before>import * as _ from 'lodash';
import * as _s from 'underscore.string';
import * as d3 from 'd3';
import {
  Directive, Input, ElementRef, OnChanges, SimpleChange, OnInit
} from '@angular/core';

@Directive({
  selector: '[qi-spark-line]'
})

/**
 * Draws a D3 spark line which plots a uniform sequential
 * one-based index vs values. The X values are the discrete
 * one-based
 * {{#crossLink "SparkLineDirective/data:property"}}{{/crossLink}}
 * indexes. The
 * {{#crossLink "SparkLineDirective/data:property"}}{{/crossLink}}
 * items are the Y axis data points.
 *
 * @class SparkLineDirective
 */
export class SparkLineDirective implements OnChanges, OnInit {
  /**
   * The data objects. The data can be either an input array for
   * a single data series or a {_series_: array, ...} for one or
   * more data series.
   *
   * @property data {Object|Object[]}
   */
  @Input() data: Object|Object[];

  /**
   * The [min, max] domain extent.
   * The default is the data min and max.
   *
   * @property domain {number[]}
   */
  @Input() domain: number[];

  /**
   * The optional X value accessor, used as follows:
   * * If the input is a string, the X accessor is the
   *   property path accessor.
   * * Otherwise, if the input is a
   *   {{#crossLink "ValueAccessor"}}{{/crossLink}},
   *   then the X accessor is that function,
   * * Otherwise, if the input is missing, then the
   *   default X accessor is the data point index.
   *
   * @property x {any}
   */
  @Input() x: any;

  /**
   * The optional Y value accessor, used as follows:
   * * If the input is a string, the Y accessor is the
   *   property path accessor.
   * * Otherwise, if the input is a
   *   {{#crossLink "ValueAccessor"}}{{/crossLink}},
   *   then the Y accessor is that function,
   * * Otherwise, if the input is missing, then the
   *   default Y accessor is the identity function.
   *
   * @property y {any}
   */
  @Input() y: any;

  /**
   * The optional additional data access argument.
   *
   * @property extra {any}
   */
  @Input() extra: any;

  /**
   * The optional domain arrays, used as folows:
   * * If the input is an array of two items, then the
   *   Y domain is that input.
   * * Otherwise, if the input is a {x, y} object, e.g.
   * `{x: [0, 12], y: [1, 100]}`, then the X and Y domains
   * are the respective property values.
   *
   * The default X or Y domain is the respective mapped data
   * min and max.
   *
   * @property domain {any}
   */
  @Input() domain: any;

  /**
   * The line width.
   *
   * @property width {number}
   */
  @Input() width;

  /**
   * The line height.
   *
   * @property height {number}
   */
  @Input() height;

  /**
   * A flag indicating whether to draw a dotted
   * vertical guide line in the middle of the
   * spark line.
   *
   * @property guide {boolean}
   */
  @Input() guide;

  /**
   * The {_series_: _label_} legend. Default for a
   * single series is no legend, otherwise the default
   * is the data key.
   *
   * @property legend {Object}
   */
  @Input() legend;

  /**
   * The D3 SVG root group element.
   *
   * @property svg {d3.Selection<any>}
   */
  private svg: d3.Selection<any>;

  /**
   * The D3 line.
   *
   * @property line {d3.Line<number, number>}
   */
  private line: d3.Line<number, number>;

  /**
   * The directive element.
   *
   * @property elementRef {ElementRef}
   */
  private elementRef: ElementRef;

  constructor(elementRef: ElementRef) {
    this.elementRef = elementRef;
  }

  ngOnChanges(changes: SimpleChange) {
    let change = changes['data'];
    if (change && !change.isFirstChange()) {
      // Draw the new values.
      let input = change.currentValue;
      let data = _.isArray(input) ? {series: input} : input;
      for (let key in data) {
        this.svg.select(`path.${ key }`)
          .attr('d', this.line(data[key]));
      }
    }
  }

  ngOnInit() {
    // Convert a simple array data input to a legendless
    // {data: input} object.<commit_msg>Add changes note comment.<commit_after>import * as _ from 'lodash';
import * as _s from 'underscore.string';
import * as d3 from 'd3';
import {
  Directive, Input, ElementRef, OnChanges, SimpleChange, OnInit
} from '@angular/core';

@Directive({
  selector: '[qi-spark-line]'
})

/**
 * Draws a D3 spark line which plots a uniform sequential
 * one-based index vs values. The X values are the discrete
 * one-based
 * {{#crossLink "SparkLineDirective/data:property"}}{{/crossLink}}
 * indexes. The
 * {{#crossLink "SparkLineDirective/data:property"}}{{/crossLink}}
 * items are the Y axis data points.
 *
 * @class SparkLineDirective
 */
export class SparkLineDirective implements OnChanges, OnInit {
  /**
   * The data objects. The data can be either an input array for
   * a single data series or a {_series_: array, ...} for one or
   * more data series.
   *
   * @property data {Object|Object[]}
   */
  @Input() data: Object|Object[];

  /**
   * The [min, max] domain extent.
   * The default is the data min and max.
   *
   * @property domain {number[]}
   */
  @Input() domain: number[];

  /**
   * The optional X value accessor, used as follows:
   * * If the input is a string, the X accessor is the
   *   property path accessor.
   * * Otherwise, if the input is a
   *   {{#crossLink "ValueAccessor"}}{{/crossLink}},
   *   then the X accessor is that function,
   * * Otherwise, if the input is missing, then the
   *   default X accessor is the data point index.
   *
   * @property x {any}
   */
  @Input() x: any;

  /**
   * The optional Y value accessor, used as follows:
   * * If the input is a string, the Y accessor is the
   *   property path accessor.
   * * Otherwise, if the input is a
   *   {{#crossLink "ValueAccessor"}}{{/crossLink}},
   *   then the Y accessor is that function,
   * * Otherwise, if the input is missing, then the
   *   default Y accessor is the identity function.
   *
   * @property y {any}
   */
  @Input() y: any;

  /**
   * The optional additional data access argument.
   *
   * @property extra {any}
   */
  @Input() extra: any;

  /**
   * The optional domain arrays, used as folows:
   * * If the input is an array of two items, then the
   *   Y domain is that input.
   * * Otherwise, if the input is a {x, y} object, e.g.
   * `{x: [0, 12], y: [1, 100]}`, then the X and Y domains
   * are the respective property values.
   *
   * The default X or Y domain is the respective mapped data
   * min and max.
   *
   * @property domain {any}
   */
  @Input() domain: any;

  /**
   * The line width.
   *
   * @property width {number}
   */
  @Input() width;

  /**
   * The line height.
   *
   * @property height {number}
   */
  @Input() height;

  /**
   * A flag indicating whether to draw a dotted
   * vertical guide line in the middle of the
   * spark line.
   *
   * @property guide {boolean}
   */
  @Input() guide;

  /**
   * The {_series_: _label_} legend. Default for a
   * single series is no legend, otherwise the default
   * is the data key.
   *
   * @property legend {Object}
   */
  @Input() legend;

  /**
   * The D3 SVG root group element.
   *
   * @property svg {d3.Selection<any>}
   */
  private svg: d3.Selection<any>;

  /**
   * The D3 line.
   *
   * @property line {d3.Line<number, number>}
   */
  private line: d3.Line<number, number>;

  /**
   * The directive element.
   *
   * @property elementRef {ElementRef}
   */
  private elementRef: ElementRef;

  constructor(elementRef: ElementRef) {
    this.elementRef = elementRef;
  }

  /**
   * Handle the following changes:
   * * If the data changed, then reset the line data, which will
   *   induce d3 to replot the line.
   *
   * _Note_: the other inputs are for initialization only, and
   * changes to them are ignored. For example, resizing the window
   * resets the width input, but that is ignored. Handling a resize
   * necessitates detaching and recreating the entire plot, which
   * results in a DOM memory leak.
   */
  ngOnChanges(changes: SimpleChange) {
    let dataChange = changes['data'];
    if (dataChange && !dataChange.isFirstChange()) {
      // Draw the new values.
      let input = dataChange.currentValue;
      let data = _.isArray(input) ? {series: input} : input;
      for (let key in data) {
        this.svg.select(`path.${ key }`)
          .attr('d', this.line(data[key]));
      }
    }
  }

  /**
   * Makes a new D3 SVG root group element and draws the plot.
   */
  ngOnInit() {
    // Convert simple array input to a {series: data} specification.
{'fraction_non_alphanumeric': 0.12685607389220158, 'fraction_numerical': 0.003975213375423828, 'mean_word_length': 2.6092827004219408, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, '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': '4542937', 'n_tokens_mistral': 2788, 'n_tokens_neox': 2720, 'n_words': 996}