<commit_before>/*** @jsx React.DOM */
var moment = require("moment");
var React = require("react");

var TooltipTrigger = require("./TooltipTrigger");

var BarChart = React.createClass({
  propTypes: {
    points: React.PropTypes.arrayOf(React.PropTypes.shape({
      x: React.PropTypes.number.isRequired,
      y: React.PropTypes.number.isRequired,
      label: React.PropTypes.string
    })),
    interval: React.PropTypes.string,
    placement: React.PropTypes.string,
    label: React.PropTypes.string
  },

  getDefaultProps(){
    return {
      placement: "bottom",
      points: [],
      label: "events"
    };
  },

  floatFormat(number, places) {
      var multi = Math.pow(10, places);
      return parseInt(number * multi, 10) / multi;
  },

  timeLabelAsHour(point) {
    var timeMoment = moment(point.x * 1000);
    var nextMoment = timeMoment.clone().add(59, "minute");

    return (
      <span>
        {timeMoment.format("LL")}<br />
        {timeMoment.format("LT")} &mdash;&rsaquo; {nextMoment.format("LT")}
      </span>
    );
  },

  timeLabelAsDay(point) {
    var timeMoment = moment(point.x * 1000);
    var nextMoment = timeMoment.clone().add(59, "minute");

    return (
      <span>
        {timeMoment.format("LL")}
      </span>
    );
  },

  timeLabelAsRange(interval, point) {
    var timeMoment = moment(point.x * 1000);
    var nextMoment = timeMoment.clone().add(interval - 1, "second");

    return (
      <span>
        {timeMoment.format("lll")}<br />
        &mdash;&rsaquo; {nextMoment.format("lll")}
      </span>
    );
  },

  timeLabelAsFull(point) {
    var timeMoment = moment(point.x * 1000);
    return timeMoment.format("lll");
  },

  render(){
    var points = this.props.points;
    var maxval = 10;
    points.forEach(function(point){
      if (point.y > maxval) {
        maxval = point.y;
      }
    });

    var pointWidth = this.floatFormat(100.0 / points.length, 2) + "%";

    var interval = (points.length > 1 ? points[1].x - points[0].x : null);
    var timeLabelFunc;
    switch (interval) {
      case 3600:
        timeLabelFunc = this.timeLabelAsHour;
        break;
      case 86400:
        timeLabelFunc = this.timeLabelAsDay;
        break;
      case null:
        timeLabelFunc = this.timeLabelAsFull;
        break;
      default:
        timeLabelFunc = this.timeLabelAsRange.bind(this, interval);
    }

    var children = points.map((point, pointIdx) => {
      var pct = this.floatFormat(point.y / maxval * 99, 2) + "%";
      var timeLabel = timeLabelFunc(point);

      var title = (
        <div style={{minWidth: 120}}>
          {point.y} {this.props.label}<br/>
          {timeLabel}
        </div>
      );
      if (point.label) {
        title += <div>({point.label})</div>;
      }

      return (
        <TooltipTrigger
            placement={this.props.placement}
            key={point.x}
            title={title}>
          <a style={{width: pointWidth}}>
            <span style={{height: pct}}>{point.y}</span>
          </a>
        </TooltipTrigger>
      );
    });

    return (
      <figure className={this.props.className || '' + ' barchart'}
              height={this.props.height}
              width={this.props.width}>
        <span className="max-y" key="max-y">{maxval}</span>
        <span className="min-y" key="min-y">{0}</span>
        {children}
      </figure>
    );
  }
});

module.exports = BarChart;
<commit_msg>Optimize BarChart render<commit_after>/*** @jsx React.DOM */
var moment = require("moment");
var React = require("react");

var TooltipTrigger = require("./TooltipTrigger");

var BarChart = React.createClass({
  propTypes: {
    points: React.PropTypes.arrayOf(React.PropTypes.shape({
      x: React.PropTypes.number.isRequired,
      y: React.PropTypes.number.isRequired,
      label: React.PropTypes.string
    })),
    interval: React.PropTypes.string,
    placement: React.PropTypes.string,
    label: React.PropTypes.string
  },

  getDefaultProps(){
    return {
      placement: "bottom",
      points: [],
      label: "events"
    };
  },

  floatFormat(number, places) {
      var multi = Math.pow(10, places);
      return parseInt(number * multi, 10) / multi;
  },

  timeLabelAsHour(point) {
    var timeMoment = moment(point.x * 1000);
    var nextMoment = timeMoment.clone().add(59, "minute");

    return (
      <span>
        {timeMoment.format("LL")}<br />
        {timeMoment.format("LT")} &mdash;&rsaquo; {nextMoment.format("LT")}
      </span>
    );
  },

  timeLabelAsDay(point) {
    var timeMoment = moment(point.x * 1000);
    var nextMoment = timeMoment.clone().add(59, "minute");

    return (
      <span>
        {timeMoment.format("LL")}
      </span>
    );
  },

  timeLabelAsRange(interval, point) {
    var timeMoment = moment(point.x * 1000);
    var nextMoment = timeMoment.clone().add(interval - 1, "second");

    return (
      <span>
        {timeMoment.format("lll")}<br />
        &mdash;&rsaquo; {nextMoment.format("lll")}
      </span>
    );
  },

  timeLabelAsFull(point) {
    var timeMoment = moment(point.x * 1000);
    return timeMoment.format("lll");
  },

  shouldComponentUpdate(nextProps, nextState) {
    var curPoints = this.props.points || [];
    var nextPoints = nextProps.points || [];
    for (var i = 0; i < Math.max(curPoints.length, nextPoints.length); i++) {
      if (!curPoints[i]) {
        return true;
      }
      if (!nextPoints[i]) {
        return true;
      }
      if (curPoints[i].x != nextPoints[i].x) {
        return true;
      }
      if (curPoints[i].y != nextPoints[i].y) {
        return true;
      }
    }
    return false;
  },

  render(){
    var points = this.props.points;
    var maxval = 10;
    points.forEach(function(point){
      if (point.y > maxval) {
        maxval = point.y;
      }
    });

    var pointWidth = this.floatFormat(100.0 / points.length, 2) + "%";

    var interval = (points.length > 1 ? points[1].x - points[0].x : null);
    var timeLabelFunc;
    switch (interval) {
      case 3600:
        timeLabelFunc = this.timeLabelAsHour;
        break;
      case 86400:
        timeLabelFunc = this.timeLabelAsDay;
        break;
      case null:
        timeLabelFunc = this.timeLabelAsFull;
        break;
      default:
        timeLabelFunc = this.timeLabelAsRange.bind(this, interval);
    }

    var children = points.map((point, pointIdx) => {
      var pct = this.floatFormat(point.y / maxval * 99, 2) + "%";
      var timeLabel = timeLabelFunc(point);

      var title = (
        <div style={{minWidth: 120}}>
          {point.y} {this.props.label}<br/>
          {timeLabel}
        </div>
      );
      if (point.label) {
        title += <div>({point.label})</div>;
      }

      return (
        <TooltipTrigger
            placement={this.props.placement}
            key={point.x}
            title={title}>
          <a style={{width: pointWidth}}>
            <span style={{height: pct}}>{point.y}</span>
          </a>
        </TooltipTrigger>
      );
    });

    return (
      <figure className={this.props.className || '' + ' barchart'}
              height={this.props.height}
              width={this.props.width}>
        <span className="max-y" key="max-y">{maxval}</span>
        <span className="min-y" key="min-y">{0}</span>
        {children}
      </figure>
    );
  }
});

module.exports = BarChart;

{'fraction_non_alphanumeric': 0.15882034632034633, 'fraction_numerical': 0.013933982683982684, 'mean_word_length': 2.251099384344767, 'pattern_counts': {'":': 0, '<': 54, '<?xml version=': 0, '>': 59, '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': '2008720', 'n_tokens_mistral': 2513, 'n_tokens_neox': 2403, 'n_words': 446}