<commit_before>/*eslint-env browser */
/*global require: false, module: false */

'use strict';

require('../css/km.css');
var _ = require('./underscore_ext');
var React = require('react');
var { PropTypes } = React;
var Modal = require('react-bootstrap/lib/Modal');
var { ListGroup, ListGroupItem, OverlayTrigger, Tooltip } = require('react-bootstrap/lib/');
var Axis = require('./Axis');
var {deepPureRenderMixin} = require('./react-utils');
var {linear, linearTicks} = require('./scale');
// XXX Warn on duplicate patients, and list patient ids?

// Basic sizes. Should make these responsive. How to make the svg responsive?
var margin = {top: 20, right: 50, bottom: 30, left: 50};
const HOVER = 'hover';

// XXX point at 100%? [xdomain[0] - 1, 1]
function line(xScale, yScale, values) {
	var coords = values.map(({t, s}) => [xScale(t), yScale(s)]);
	return ['M0,0', ...coords.map(([t, s]) => `H${t}V${s}`)].join(' ');
}

function censorLines(xScale, yScale, censors, className) {
	/*eslint-disable comma-spacing */
	return censors.map(({t, s}, i) =>
		<line
			key={i}
			className={className}
			x1={0} x2={0} y1={-5} y2={5}
			transform={`translate(${xScale(t)},${yScale(s)})`} />
	);
	/*eslint-enable comma-spacing */
}

function calcDims (viewDims, sizeRatios) {
	return _.mapObject(sizeRatios, (section) => {
		return _.mapObject(section, (ratio, side) => viewDims[side] * ratio);
	});
}

function checkIfActive(currentLabel, activeLabel) {
	// check whether this line group should be set to Active
	if (activeLabel)
		return (activeLabel === currentLabel);
	else
		return false;
}

var LineGroup = React.createClass({
	getInitialState: function() {
		return { isActive: false }
	},

	componentWillReceiveProps: function(newProps) {
		let { g, activeLabel } = newProps,
			[ , label, ] = g,
			oldIsActive = this.state.isActive,
			activeStatus = checkIfActive(label, activeLabel);

		if (oldIsActive != activeStatus)
			this.setState({ isActive: activeStatus });
	},

	shouldComponentUpdate: function(newProps, newState) {
		//testing for any changes to g, and state's isActive parameter should be sufficient
		let gChanged = !_.isEqual(newProps.g, this.props.g),
			isActiveChanged = !_.isEqual(newState.isActive, this.state.isActive);

		return (gChanged || isActiveChanged);
	},

	render: function() {
		let { xScale, yScale, g, setActiveLabel } = this.props;
		let [ color, label, curve ] = g;
		var censors = curve.filter(pt => !pt.e);
		let activeLabelClassName = this.state.isActive ? HOVER : '';

		return (
			<g key={label} className='subgroup' stroke={color}
				onMouseOver={(e) => setActiveLabel(e, label)}
				onMouseOut={(e) => setActiveLabel(e, '')}>
				<path className={`outline ${activeLabelClassName}`} d={line(xScale, yScale, curve)}/>
				<path className={`line ${activeLabelClassName}`} d={line(xScale, yScale, curve)}/>
				{censorLines(xScale, yScale, censors, `outline ${activeLabelClassName}`)}
				{censorLines(xScale, yScale, censors, `line' ${activeLabelClassName}`)}
			</g>
		);
	}
});

var bounds = x => [_.min(x), _.max(x)];

function svg({colors, labels, curves}, setActiveLabel, activeLabel, size) {
	var height = size.height - margin.top - margin.bottom,
		width = size.width,
		xdomain = bounds(_.pluck(_.flatten(curves), 't')),
		xrange = [0, width],
		ydomain = [0, 1],
		yrange = [height, 0],
		xScale = linear(xdomain, xrange),
		yScale = linear(ydomain, yrange);

	var groupSvg = _.zip(colors, labels, curves).map((g, index) => {
		return (<LineGroup
				key={index}
				xScale={xScale}
				yScale={yScale}
				g={g}
				activeLabel={activeLabel}
				setActiveLabel={setActiveLabel} />);
	});

	/*eslint-disable comma-spacing */
	return (
		<svg width={width} height={size.height}>
			<g transform={`translate(${margin.left}, ${margin.top})`}>
				<Axis<commit_msg>Fix & adjust margin calculation in km.<commit_after>/*eslint-env browser */
/*global require: false, module: false */

'use strict';

require('../css/km.css');
var _ = require('./underscore_ext');
var React = require('react');
var { PropTypes } = React;
var Modal = require('react-bootstrap/lib/Modal');
var { ListGroup, ListGroupItem, OverlayTrigger, Tooltip } = require('react-bootstrap/lib/');
var Axis = require('./Axis');
var {deepPureRenderMixin} = require('./react-utils');
var {linear, linearTicks} = require('./scale');
// XXX Warn on duplicate patients, and list patient ids?

// Basic sizes. Should make these responsive. How to make the svg responsive?
var margin = {top: 20, right: 10, bottom: 30, left: 50};
const HOVER = 'hover';

// XXX point at 100%? [xdomain[0] - 1, 1]
function line(xScale, yScale, values) {
	var coords = values.map(({t, s}) => [xScale(t), yScale(s)]);
	return ['M0,0', ...coords.map(([t, s]) => `H${t}V${s}`)].join(' ');
}

function censorLines(xScale, yScale, censors, className) {
	/*eslint-disable comma-spacing */
	return censors.map(({t, s}, i) =>
		<line
			key={i}
			className={className}
			x1={0} x2={0} y1={-5} y2={5}
			transform={`translate(${xScale(t)},${yScale(s)})`} />
	);
	/*eslint-enable comma-spacing */
}

function calcDims (viewDims, sizeRatios) {
	return _.mapObject(sizeRatios, (section) => {
		return _.mapObject(section, (ratio, side) => viewDims[side] * ratio);
	});
}

function checkIfActive(currentLabel, activeLabel) {
	// check whether this line group should be set to Active
	if (activeLabel)
		return (activeLabel === currentLabel);
	else
		return false;
}

var LineGroup = React.createClass({
	getInitialState: function() {
		return { isActive: false }
	},

	componentWillReceiveProps: function(newProps) {
		let { g, activeLabel } = newProps,
			[ , label, ] = g,
			oldIsActive = this.state.isActive,
			activeStatus = checkIfActive(label, activeLabel);

		if (oldIsActive != activeStatus)
			this.setState({ isActive: activeStatus });
	},

	shouldComponentUpdate: function(newProps, newState) {
		//testing for any changes to g, and state's isActive parameter should be sufficient
		let gChanged = !_.isEqual(newProps.g, this.props.g),
			isActiveChanged = !_.isEqual(newState.isActive, this.state.isActive);

		return (gChanged || isActiveChanged);
	},

	render: function() {
		let { xScale, yScale, g, setActiveLabel } = this.props;
		let [ color, label, curve ] = g;
		var censors = curve.filter(pt => !pt.e);
		let activeLabelClassName = this.state.isActive ? HOVER : '';

		return (
			<g key={label} className='subgroup' stroke={color}
				onMouseOver={(e) => setActiveLabel(e, label)}
				onMouseOut={(e) => setActiveLabel(e, '')}>
				<path className={`outline ${activeLabelClassName}`} d={line(xScale, yScale, curve)}/>
				<path className={`line ${activeLabelClassName}`} d={line(xScale, yScale, curve)}/>
				{censorLines(xScale, yScale, censors, `outline ${activeLabelClassName}`)}
				{censorLines(xScale, yScale, censors, `line' ${activeLabelClassName}`)}
			</g>
		);
	}
});

var bounds = x => [_.min(x), _.max(x)];

function svg({colors, labels, curves}, setActiveLabel, activeLabel, size) {
	var height = size.height - margin.top - margin.bottom,
		width = size.width - margin.left - margin.right,
		xdomain = bounds(_.pluck(_.flatten(curves), 't')),
		xrange = [0, width],
		ydomain = [0, 1],
		yrange = [height, 0],
		xScale = linear(xdomain, xrange),
		yScale = linear(ydomain, yrange);

	var groupSvg = _.zip(colors, labels, curves).map((g, index) => {
		return (<LineGroup
				key={index}
				xScale={xScale}
				yScale={yScale}
				g={g}
				activeLabel={activeLabel}
				setActiveLabel={setActiveLabel} />);
	});

	/*eslint-disable comma-spacing */
	return (
		<svg width={size.width} height={size.height}>
			<g transform={`translate(${margin.left}, ${margin.top})`}>
				<Axis
{'fraction_non_alphanumeric': 0.17738791423001948, 'fraction_numerical': 0.007277452891487979, 'mean_word_length': 4.431192660550459, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 39, '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': '1295908', 'n_tokens_mistral': 2861, 'n_tokens_neox': 2620, 'n_words': 638}