import React, {Component} from 'react';
import PropTypes from 'prop-types';
import CircleHelper from "../../../Utils/Feedback/CircleHelper";
import CustomTextField from "../../../Utils/Inputs/CustomTextField";
import StyledSlider from "../../../Utils/Inputs/StyledSlider";
import styles from "./styles/Calculations.module.css";
const tooltip = {
mainSimple: " is used when calculating lower approximations of unions of ordered decision classes " +
"according to the Variable Consistency Dominance-based Rough Set Approach (VC-DRSA). " +
"In VC-DRSA, an object y, belonging to a union of ordered decision classes X, " +
"is considered to belong to the lower approximation of X if selected consistency measure, " +
"calculated with respect to y and X, satisfies considered consistency threshold t. " +
"Note that for a gain-type consistency measure, like rough membership, one checks if measure’s value is \u2265 t. " +
"However, for a cost-type consistency measure, like epsilon, one checks if measure’s value is \u2264 t.",
mainExtended: " is used when calculating lower approximations of unions of ordered decision classes " +
"according to the Variable Consistency Dominance-based Rough Set Approach (VC-DRSA), " +
"and then, when inducing decision rules. " +
"In VC-DRSA, an object y, belonging to a union of ordered decision classes X, " +
"is considered to belong to the lower approximation of X if selected consistency measure, " +
"calculated with respect to y and X, satisfies considered consistency threshold t. " +
"Note that for a gain-type consistency measure, like rough membership, one checks if measure’s value is \u2265 t. " +
"However, for a cost-type consistency measure, like epsilon, one checks if measure’s value is \u2264 t.",
};
/**
* <h3>Overview</h3>
* Presents threshold and allows user to choose on the slider or type new value.
*
* @name Threshold
* @constructor
* @category Project
* @subcategory Calculations
* @param {Object} props
* @param {Object} props.CircleHelperProps - Props applied to the {@link CircleHelper} element.
* @param {boolean} [props.keepChanges=true] - If <code>false</code> changes aren't stored in the state.
* @param {function} props.onChange - Callback fired when value changed.
* @param {Object} props.SliderProps - Props applied to the {@link StyledSlider} element.
* @param {Object} props.TextFieldProps - Props applied to the {@link CustomTextField} element.
* @param {*} props.value - The current threshold value.
* @param {"simple"|"extended"} [props.variant="simple"] - Determines what text should be displayed in the tooltip.
* @returns {React.ReactElement}
*/
class ThresholdSelector extends Component {
constructor(props) {
super(props);
this.state = {
threshold: 0,
};
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
return nextState.threshold !== this.state.threshold || nextProps.value !== this.props.value;
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (prevProps.value !== this.props.value) {
this.setState({
threshold: this.props.value,
});
}
}
onInputChange = (event) => {
if (!this.props.keepChanges) return;
let input = event.target.value.toString();
if (input.includes(",")) {
input = input.replace(",", ".");
}
if (!isNaN(Number(input)) && input.length < 5) {
const regEx = new RegExp(/^[01]\.[0-9]*$/);
const typingInProgress = input === "" || regEx.test(input);
this.setState({
threshold: typingInProgress ? input : Number(input),
});
}
};
onInputBlur = () => {
this.setState(prevState => ({
threshold: Number(prevState.threshold),
}), () => {
if (this.state.threshold > 1) {
this.setState({
threshold: 1,
}, () => {
this.props.onChange(this.state.threshold);
});
} else {
this.props.onChange(this.state.threshold);
}
});
};
onSliderChange = (event, newValue) => {
if (!this.props.keepChanges) return;
this.setState({
threshold: newValue,
});
};
onSliderChangeCommitted = () => {
this.props.onChange(this.state.threshold);
};
render() {
const { threshold } = this.state;
const { CircleHelperProps, SliderProps, TextFieldProps, variant } = this.props;
return (
<div aria-label={"outer wrapper"} className={styles.OuterWrapper} style={this.props.style}>
<CircleHelper
title={
<p aria-label={"main"} style={{margin: 0, textAlign: "justify"}}>
<b>Consistency threshold</b>
{tooltip["main" + variant[0].toUpperCase() + variant.slice(1)]}
</p>
}
WrapperProps={{
style: { marginRight: 16 }
}}
{...CircleHelperProps}
/>
<div aria-label={"inner wrapper"} className={styles.InnerWrapper} style={{marginRight: 16}}>
<CustomTextField
onBlur={this.onInputBlur}
onChange={this.onInputChange}
outsideLabel={"Choose consistency threshold"}
style={{ maxWidth: 72, minWidth: 60 }}
value={threshold}
{...TextFieldProps}
/>
</div>
<StyledSlider
max={1.0}
min={0.0}
onChange={this.onSliderChange}
onChangeCommitted={this.onSliderChangeCommitted}
step={0.01}
style={{ marginRight: 24, maxWidth: 72, minWidth: 60}}
value={typeof threshold === "number" ? threshold : 0.0}
{...SliderProps}
/>
</div>
);
}
}
ThresholdSelector.propTypes = {
CircleHelperProps: PropTypes.object,
keepChanges: PropTypes.bool,
onChange: PropTypes.func,
SliderProps: PropTypes.object,
TextFieldProps: PropTypes.object,
value: PropTypes.any,
variant: PropTypes.oneOf(["simple", "extended"])
};
ThresholdSelector.defaultProps = {
keepChanges: true,
variant: "simple"
};
export default ThresholdSelector
Source