<commit_before>import React from 'react';
import { connect } from 'react-redux';
import { createAction } from '../utils/ActionCreator';
import Actions from '../constants/actions';
import { Maybe as MaybeType } from '../utils/PropTypes';
import { Maybe } from 'monet';
import { Button, Radio, FormGroup, Form, FormControl, Panel } from 'react-bootstrap';
import _ from 'lodash';

import './Game.scss';

const Game = React.createClass({
    propTypes: {
        questions: React.PropTypes.arrayOf(React.PropTypes.object.isRequired).isRequired,
        answers: React.PropTypes.arrayOf(React.PropTypes.object.isRequired).isRequired,
        gameType: React.PropTypes.oneOf(['freetext', 'multiple']).isRequired,
        currentQuestion: MaybeType,
        onInit: React.PropTypes.func.isRequired,
        onStart: React.PropTypes.func.isRequired,
        onStop: React.PropTypes.func.isRequired,
        onAnswer: React.PropTypes.func.isRequired,
        gameTypeChanged: React.PropTypes.func.isRequired
    },
    getDefaultProps: function() {
        return {
            questions: []
        };
    },
    getInitialState: function() {
        return {
            answer: ''
        };
    },
    componentDidMount: function() {
        this.props.onInit();
    },
    onAnswerChange: function(e) {
        this.setState({answer: e.target.value});
    },
    onAnswerSubmit: function(ev) {
        if (ev) {
            ev.preventDefault();
        }
        this.props.onAnswer(this.state.answer);
        this.setState(this.getInitialState());
    },
    getFeedback: function() {
        const lastAnswer = Maybe.fromNull(_.last(this.props.answers));

        const lastQuestion = lastAnswer.flatMap(answer =>
            Maybe.fromNull(this.props.questions.find(q => q.id === answer.questionId) || null)
        );

        return lastAnswer
            .flatMap(answer => lastQuestion.map(question => ({question, answer})))
            .map(({answer, question}) => answer.correct ?
                <p className="correct-answer">Correct!</p> :
                <p className="incorrect-answer">
                    Better luck next time! The correct answer was {question.answer}.
                </p>
            ).orSome(null);
    },
    getCurrentQuestion: function() {
        return this.props.currentQuestion
            .flatMap(n => Maybe.fromNull(this.props.questions[n] || null));
    },
    getGame: function() {
        if (this.props.currentQuestion.isSome()) {
            const currentNo = this.props.currentQuestion.some();
            const question = this.getCurrentQuestion();

            return question.map(q => (
                <Panel header={<h3>{q.question}</h3>}>
                    {this.getAnswerForm()}
                    <p>
                        <span className="stop-label">Got enough?</span>
                        <Button bsSize="small" bsStyle="danger" onClick={this.props.onStop}>Stop</Button>
                    </p>
                </Panel>
            )).orSome(<div>Internal error: question number {currentNo} was not found.</div>);
        } else {
            return this.getStartForm();
        }
    },
    getChoices: function() {
        if (this.props.gameType === 'freetext') {
            return null;
        } else {
            return this.getCurrentQuestion().map(q => {
                const choices = _(this.props.questions)
                    .shuffle()
                    .filter(q2 => q2.id !== q.id) // make sure the correct answer is not included twice
                    .filter(q2 => q2.answer !== q.answer) // make sure answers identical to the correct one are not included
                    .uniqBy('answer') // make sure two (different) questions with identical answers are not included
                    .take(3)
                    .concat(q)
                    .shuffle()
                    .compact() // remove empty ones in case there are less than 4 unique answers
                    .valueOf();
                return choices.map(choice =>
                    <Button key={choice.id} bsSize="large" block onClick={() => this.props.onAnswer(choice.answer)}>{choice.answer}</Button>
                );
            }).orSome(<div className="error">Internal error: no question {this.props.currentQuestion} found.</div>);
        }
    },
    getAnswerForm: function() {
        if (this.props.gameType === 'freetext') {
            return (
                <Form inline>
                    <FormGroup>
                        <FormControl
                            value={this.state.answer}
                            onKeyPress={(ev) => ev.key === 'Enter' ? this.onAnswerSubmit(ev) : null}
                            onChange={this.onAnswerChange} />
                    </FormGroup>
                    <Button>Answer</Button>
                </Form>
            );
        } else {
            return (
                <div className="choice-list">
                    {this.getChoices()}
                </div>
            );
        }<commit_msg>fix bug with answer button having no effect<commit_after>import React from 'react';
import { connect } from 'react-redux';
import { createAction } from '../utils/ActionCreator';
import Actions from '../constants/actions';
import { Maybe as MaybeType } from '../utils/PropTypes';
import { Maybe } from 'monet';
import { Button, Radio, FormGroup, Form, FormControl, Panel } from 'react-bootstrap';
import _ from 'lodash';

import './Game.scss';

const Game = React.createClass({
    propTypes: {
        questions: React.PropTypes.arrayOf(React.PropTypes.object.isRequired).isRequired,
        answers: React.PropTypes.arrayOf(React.PropTypes.object.isRequired).isRequired,
        gameType: React.PropTypes.oneOf(['freetext', 'multiple']).isRequired,
        currentQuestion: MaybeType,
        onInit: React.PropTypes.func.isRequired,
        onStart: React.PropTypes.func.isRequired,
        onStop: React.PropTypes.func.isRequired,
        onAnswer: React.PropTypes.func.isRequired,
        gameTypeChanged: React.PropTypes.func.isRequired
    },
    getDefaultProps: function() {
        return {
            questions: []
        };
    },
    getInitialState: function() {
        return {
            answer: ''
        };
    },
    componentDidMount: function() {
        this.props.onInit();
    },
    onAnswerChange: function(e) {
        this.setState({answer: e.target.value});
    },
    onAnswerSubmit: function(ev) {
        if (ev) {
            ev.preventDefault();
        }
        this.props.onAnswer(this.state.answer);
        this.setState(this.getInitialState());
    },
    getFeedback: function() {
        const lastAnswer = Maybe.fromNull(_.last(this.props.answers));

        const lastQuestion = lastAnswer.flatMap(answer =>
            Maybe.fromNull(this.props.questions.find(q => q.id === answer.questionId) || null)
        );

        return lastAnswer
            .flatMap(answer => lastQuestion.map(question => ({question, answer})))
            .map(({answer, question}) => answer.correct ?
                <p className="correct-answer">Correct!</p> :
                <p className="incorrect-answer">
                    Better luck next time! The correct answer was {question.answer}.
                </p>
            ).orSome(null);
    },
    getCurrentQuestion: function() {
        return this.props.currentQuestion
            .flatMap(n => Maybe.fromNull(this.props.questions[n] || null));
    },
    getGame: function() {
        if (this.props.currentQuestion.isSome()) {
            const currentNo = this.props.currentQuestion.some();
            const question = this.getCurrentQuestion();

            return question.map(q => (
                <Panel header={<h3>{q.question}</h3>}>
                    {this.getAnswerForm()}
                    <p>
                        <span className="stop-label">Got enough?</span>
                        <Button bsSize="small" bsStyle="danger" onClick={this.props.onStop}>Stop</Button>
                    </p>
                </Panel>
            )).orSome(<div>Internal error: question number {currentNo} was not found.</div>);
        } else {
            return this.getStartForm();
        }
    },
    getChoices: function() {
        if (this.props.gameType === 'freetext') {
            return null;
        } else {
            return this.getCurrentQuestion().map(q => {
                const choices = _(this.props.questions)
                    .shuffle()
                    .filter(q2 => q2.id !== q.id) // make sure the correct answer is not included twice
                    .filter(q2 => q2.answer !== q.answer) // make sure answers identical to the correct one are not included
                    .uniqBy('answer') // make sure two (different) questions with identical answers are not included
                    .take(3)
                    .concat(q)
                    .shuffle()
                    .compact() // remove empty ones in case there are less than 4 unique answers
                    .valueOf();
                return choices.map(choice =>
                    <Button key={choice.id} bsSize="large" block onClick={() => this.props.onAnswer(choice.answer)}>{choice.answer}</Button>
                );
            }).orSome(<div className="error">Internal error: no question {this.props.currentQuestion} found.</div>);
        }
    },
    getAnswerForm: function() {
        if (this.props.gameType === 'freetext') {
            return (
                <Form inline>
                    <FormGroup>
                        <FormControl
                            value={this.state.answer}
                            onKeyPress={(ev) => ev.key === 'Enter' ? this.onAnswerSubmit(ev) : null}
                            onChange={this.onAnswerChange} />
                    </FormGroup>
                    <Button onClick={ev => this.onAnswerSubmit(ev)}>Answer</Button>
                </Form>
            );
        } else {
            return (
                <div className="choice-list">
                    {this.getChoices()}
                </div>
            );
        }
{'fraction_non_alphanumeric': 0.1295530616263044, 'fraction_numerical': 0.0015751132112620594, 'mean_word_length': 1.7620989668297988, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 88, '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': '6841451', 'n_tokens_mistral': 2735, 'n_tokens_neox': 2620, 'n_words': 557}