<commit_before>import React from 'react';
import {connect} from 'react-redux';

import {updateProperty} from '../../actions/simple-actions';

class PageRanking extends React.Component {
    constructor(props) {
        super(props);
        this.texts = {
            postWeight            : {
                title: 'Weight: Post',
                hint : 'Points given for every post'
            },
            topicWeight           : {
                title: 'Weight: Topic',
                hint : 'Points given for every created topic'
            },
            reputationWeight      : {
                title: 'Weight: Reputation',
                hint : 'Points given for reputation grow'
            },
            reputationActionWeight: {
                title: 'Weight: Reputation Action',
                hint : `Points given for increasing someone's reputation`
            },
            basePoints            : {
                title: 'Base Points',
                hint : 'Points needed to achieve very first level up'
            },
            baseGrow              : {
                title: 'Base Grow',
                hint : 'Determines how many extra points needed to achieve every next level'
            }
        };
    }

    createButton() {
        return (
            <button
                className="btn btn-primary"
                type="button"
                onClick={() => {}}><i className="fa fa-floppy-o"></i> Save Changes
            </button>
        );
    }

    generateFields(fields) {
        // Convert to N columns, possible values - 2, 3, 4, 6, 12
        let columns = 2, rows = [], index = 0, cursor = 0;
        let columnClass = `col-md-${12 / columns}`;

        for (let key of fields.keys()) {
            if (!rows[index]) {
                rows[index] = [];
            }
            rows[index].push(key);

            cursor++;
            if (cursor % columns == 0) {
                index++;
            }
        }

        return (
            <div>
                {rows.map(columnList => {
                    return (
                        <div className="row">
                            {columnList.map(fieldKey => {
                                let textData = this.texts[fieldKey];
                                return (
                                    <div className={columnClass}>
                                        <div className='form-group'>
                                            <label htmlFor={fieldKey}>{textData.title}</label>
                                            <input
                                                type="number"
                                                className="form-control"
                                                id={fieldKey}
                                                value={this.props.calculationProperties.get(fieldKey)}
                                                onChange={(e) => this.propertyDidChange(fieldKey, e.target.value)}/>
                                            {textData.hint}
                                        </div>
                                    </div>
                                );
                            })}
                        </div>
                    );
                })}
            </div>
        );
    }

    propertyDidChange(property, value) {
        console.log(`Property ${property} did change, value: ${value}`);
        this.props.dispatch(updateProperty(property, value));
    }

    render() {
        let saveButton = (this.props.calculationPropertiesChanged) ? this.createButton() : null;
        return (
            <div className="row">
                <div className="col-md-8">
                    {this.generateFields(this.props.calculationProperties)}
                    {saveButton}
                </div>
            </div>
        );
    }
}

export default connect(state => {
    return {
        calculationProperties       : state.calculationProperties,
        calculationPropertiesChanged: state.calculationPropertiesChanged
    };
})(PageRanking);
<commit_msg>add preview for points values<commit_after>import React from 'react';
import {connect} from 'react-redux';

import {updateProperty} from '../../actions/simple-actions';

class PageRanking extends React.Component {
    constructor(props) {
        super(props);
        this.texts = {
            postWeight            : {
                title: 'Weight: Post',
                hint : 'Points given for every post'
            },
            topicWeight           : {
                title: 'Weight: Topic',
                hint : 'Points given for every created topic'
            },
            reputationWeight      : {
                title: 'Weight: Reputation',
                hint : 'Points given for reputation grow'
            },
            reputationActionWeight: {
                title: 'Weight: Reputation Action',
                hint : `Points given for increasing someone's reputation`
            },
            basePoints            : {
                title: 'Base Points',
                hint : 'Points needed to achieve very first level up'
            },
            baseGrow              : {
                title: 'Base Grow',
                hint : 'Determines how many extra points needed to achieve every next level'
            }
        };
    }

    // FIXME DRY, try to use same Ranking calculation which is provided for the client side
    calculateLevels(basePoints, baseGrow) {
        let accumulatedPoints = 0,
            level             = 1,
            currentLevelTotal = parseInt(basePoints, 10),
            levelGrow         = parseInt(baseGrow, 10),
            preview           = [10, 20, 30, 40, 50, 60, 70, 80, 99],
            previewIndex      = -1,
            result            = [];

        while (level < 100) {
            level++;
            accumulatedPoints += currentLevelTotal;
            currentLevelTotal += levelGrow;

            previewIndex = preview.indexOf(level);
            if (previewIndex != -1) {
                result.push({level, accumulatedPoints});
            }
        }

        return result;
    }

    createButton() {
        return (
            <button
                className="btn btn-primary"
                type="button"
                onClick={() => {}}><i className="fa fa-floppy-o"></i> Save Changes
            </button>
        );
    }

    generateFields(fields) {
        // Convert to N columns, possible values - 2, 3, 4, 6, 12
        let columns = 2, rows = [], index = 0, cursor = 0;
        let columnClass = `col-md-${12 / columns}`;

        for (let key of fields.keys()) {
            if (!rows[index]) {
                rows[index] = [];
            }
            rows[index].push(key);

            cursor++;
            if (cursor % columns == 0) {
                index++;
            }
        }

        return (
            <div>
                {rows.map(columnList => {
                    return (
                        <div className="row">
                            {columnList.map(fieldKey => {
                                let textData = this.texts[fieldKey];
                                return (
                                    <div className={columnClass}>
                                        <div className='form-group'>
                                            <label htmlFor={fieldKey}>{textData.title}</label>
                                            <input
                                                type="number"
                                                className="form-control"
                                                id={fieldKey}
                                                value={this.props.calculationProperties.get(fieldKey)}
                                                onChange={(e) => this.propertyDidChange(fieldKey, e.target.value)}/>
                                            {textData.hint}
                                        </div>
                                    </div>
                                );
                            })}
                        </div>
                    );
                })}
            </div>
        );
    }

    generateLevelPreview(basePoints, baseGrow) {
        if (basePoints == 0) {
            return <div className="alert alert-warning" role="alert">Invalid. Level Grow isn't possible.</div>
        }

        return <div>
            {this.calculateLevels(basePoints, baseGrow).map(levelData => {
                return (
                    <div className="level-preview">
                        Level {levelData.level}: {levelData.accumulatedPoints} points
                    </div>
                );
            })}
        </div>;
    }

    propertyDidChange(property, value) {
        console.log(`Property ${property} did change, value: ${value}`);
        this.props.dispatch(updateProperty(property, value));
    }

    render() {
        let saveButton = (this.props.calculationPropertiesChanged) ? this.createButton() : null;
        return (
            <div className="row">
                <div className="col-md-8">
                    {this.generateFields(this.props.calculationProperties)}
                    {saveButton}
                </div>
                <div className="col-md-4">
                    <h5>Ranking Preview: Default</h5>
                    {this.generateLevelPreview(
                        this.props.calculationProperties.get('basePoints'),
                        this.props.calculationProperties.get('baseGrow')
                    )}
                </div>
            </div>
        );
    }
}

export default connect(state => {
    return {
        calculationProperties       : state.calculationProperties,
        calculationPropertiesChanged: state.calculationPropertiesChanged
    };
})(PageRanking);

{'fraction_non_alphanumeric': 0.10173073052928154, 'fraction_numerical': 0.005936808210907627, 'mean_word_length': 1.0654613466334164, 'pattern_counts': {'":': 0, '<': 52, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 47, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2218117', 'n_tokens_mistral': 2323, 'n_tokens_neox': 2164, 'n_words': 512}