<commit_before>import React, { PropTypes } from 'react';

import ChangesLinks from 'es6!display/changes/links';
import SimpleTooltip from 'es6!display/simple_tooltip';
import { ProgrammingError } from 'es6!display/errors';
import {
  get_runnable_condition,
  get_runnable_condition_color_cls,
  get_runnable_condition_short_text
} from 'es6!display/changes/build_conditions';

/*
 * Renders a small bar chart of a series of builds/tests/maybe others
 */
export var ChangesChart = React.createClass({

  MAX_CHART_HEIGHT: 40,  // pixels
  
  propTypes: {
    type: PropTypes.oneOf(['build', 'test']).isRequired,
    runnables: PropTypes.array.isRequired,
    // if enabled, we'll show a 'latest' label
    enableLatest: PropTypes.bool
  },

  getDefaultProps() {
    return { enableLatest: true };
  },

  render() {
    var { runnables, className, } = this.props;

    // we'll render bar heights relative to this
    var longestDuration = _.chain(runnables).compact().pluck('duration').sort().last().value();

    var content = _.map(this.props.runnables, runnable => {
      var no_duration = runnable && !runnable.duration && runnable.duration === 0;
      if (_.isEmpty(runnable) || no_duration) {
        // would be nice to still show a tooltip here...
        return <div 
          className="chartBarColumn"
          style={{ paddingTop: this.MAX_CHART_HEIGHT - 2 }}>
          <div
            className="emptyChartBar"
            style={{height: 2}}
          />
        </div>;
      }

      var heightPercentage = runnable.duration / longestDuration;
      var barHeight = Math.floor(heightPercentage * this.MAX_CHART_HEIGHT) || 1;

      var columnPadding = this.MAX_CHART_HEIGHT - barHeight;
<commit_msg>Fix broken sorting in chart element height determination<commit_after>import React, { PropTypes } from 'react';

import ChangesLinks from 'es6!display/changes/links';
import SimpleTooltip from 'es6!display/simple_tooltip';
import { ProgrammingError } from 'es6!display/errors';
import {
  get_runnable_condition,
  get_runnable_condition_color_cls,
  get_runnable_condition_short_text
} from 'es6!display/changes/build_conditions';

/*
 * Renders a small bar chart of a series of builds/tests/maybe others
 */
export var ChangesChart = React.createClass({

  MAX_CHART_HEIGHT: 40,  // pixels
  
  propTypes: {
    type: PropTypes.oneOf(['build', 'test']).isRequired,
    runnables: PropTypes.array.isRequired,
    // if enabled, we'll show a 'latest' label
    enableLatest: PropTypes.bool
  },

  getDefaultProps() {
    return { enableLatest: true };
  },

  render() {
    var { runnables, className, } = this.props;

    // we'll render bar heights relative to this
    // We sortBy(identity) because using sort() sorts by string representation, which is wrong.
    var longestDuration = _.chain(runnables).compact().pluck('duration').sortBy(_.identity).last().value();

    var content = _.map(this.props.runnables, runnable => {
      var no_duration = runnable && !runnable.duration && runnable.duration === 0;
      if (_.isEmpty(runnable) || no_duration) {
        // would be nice to still show a tooltip here...
        return <div 
          className="chartBarColumn"
          style={{ paddingTop: this.MAX_CHART_HEIGHT - 2 }}>
          <div
            className="emptyChartBar"
            style={{height: 2}}
          />
        </div>;
      }

      var heightPercentage = runnable.duration / longestDuration;
      var barHeight = Math.floor(heightPercentage * this.MAX_CHART_HEIGHT) || 1;

      var columnPadding = this.MAX_CHART_HEIGHT - barHeight;

{'fraction_non_alphanumeric': 0.11704197942730053, 'fraction_numerical': 0.005560189046427579, 'mean_word_length': 3.227967097532315, 'pattern_counts': {'":': 0, '<': 9, '<?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': '5087254', 'n_tokens_mistral': 1105, 'n_tokens_neox': 1069, 'n_words': 263}