<commit_before>
/* eslint no-multi-spaces: 0 */

import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';

import CodeMirror from 'react-codemirror';

const outputOptions = {
  readOnly: true,
  theme: 'monokai',
  scrollbarStyle: 'null',
  lineWrapping: true,
  mode: '',
  json: true
};

/* Component which renders the left panel containing control buttons, test
 * description and test results.*/
export default class ChallengePanel extends React.Component {
  constructor(props) {
    super(props);
    this.createMarkup = this.createMarkup.bind(this);
  }

  getOverallTestResult () {
    if (this.props.testResults.size) {
      return this.props.testResults.every(test => test.pass);
    }
    return false;
  }

  createMarkup() {
    const descr = this.props.description.join('\n');
    return { __html: descr };
  }

  renderBenchmarkResults () {
    if (!this.props.benchmarkResults.size) {
      return;
    }

    const results = this.props.benchmarkResults.toJS();

    let className;
    if (results.resultMessage === 'Your code can be made more efficient') {
      className = 'text-warning';
    }
    else if (results.resultMessage === 'Tie. Your code is fast!') {
      className = 'text-primary';
    }
    else className = 'text-success';

    return (
      <div>
        <p className='text-default'>Benchmark result:
          <span className={className}>  {results.resultMessage}</span>
        </p>
        <p className='text-muted'>{results.stockPerf}</p>
        <p className='text-muted'>{results.userPerf}</p>
      </div>
    );
  }

  /* TODO: Add limit to the number of printed tests. Improve output. */
  renderTestResults() {
    /* eslint react/no-danger: 0 */
    const results = this.props.testResults;
    const numTests = results.size;
    let testsOk = true;
    let individualTests;

    if (numTests > 0) {
      let id = 0;
      individualTests = results.map(item => {
        const result = item.pass ? 'Pass' : 'Fail';
        const className = item.pass ? 'text-success' : 'text-danger';
        testsOk = testsOk && item.pass;
        id += 1;

        // return only status of each test on Whiteboard mode
        if (this.props.editor === 'Whiteboard') {
          return <p className={className} key={id}>Status: {result}</p>;
        }

        // If test had error, format the error message here
        let msg = null;
        if (item.error !== null) {
          const innerHtml = { __html: `Error: ${item.error}` };
          msg = <span dangerouslySetInnerHTML={innerHtml} />;
        }

        return <p className={className} key={id}>Status: {result} {msg}</p>;
      });
    }
    let finalResult = testsOk ? 'All tests passed' : 'There were failing tests';
    if (numTests === 0) {
      finalResult = 'No tests run.';
    }

    return (
      <div>
        <p>Tests result: {finalResult}</p>
        {individualTests}
      </div>
    );
  }

  render() {
    let finishButton = null;
    if (this.props.isTimerFinished && !this.props.isSessionFinished) {
      finishButton = (
        <button className='btn btn-danger' onClick={this.props.onClickFinishSession}>Finish</button>
      );
    }

    const benchmarkResults = this.renderBenchmarkResults();
    const testResults = this.renderTestResults();
    const overallTestResult = this.getOverallTestResult();
    const runTestsBtnClass = (this.props.isRunningTests || this.props.isRunningBenchmark) ? 'btn btn-primary disabled' : 'btn btn-primary';
    const runBenchmarkBtnClass = (this.props.isRunningTests || this.props.isRunningBenchmark) ? 'btn btn-info disabled' : 'btn btn-info';

    /* eslint react/no-danger: 0 */
    return (
      <div className='challenge-panel'>
        <div className='challenge__title'>{this.props.title}</div>
        {this.props.showDescription &&
        <div className='challenge__description' dangerouslySetInnerHTML={this.createMarkup()} />
        }
        <div className='challenge__buttons'>
          {!this.props.isSessionStarted &&
            <button className='btn btn-success' onClick={this.props.onClickStartChallenge}>Start</button>
          }
          {(!this.props.isSessionStarted || this.props.mode === 'Practice') &&
            <button className='btn btn-primary' onClick={this.props.onModalOpen}>Menu</button>
          }
          {this.props.isSessionStarted &&
            <button className={runTestsBtnClass} onClick={this.props.onClickRunTests}>Run tests</button>
          }
          {this.props.isSessionStarted &&
            overallTestResult &&
            this.props.benchmark !== '' &&
            <button className={runBenchmarkBtnClass} onClick={this.props.onClickBenchmark}>Benchmark</button>
          }

          {finishButton}
        </div>
        <div className='challenge__buttons'>
          {this.props.isSessionStarted &&
            <button className='btn btn-warning' onClick={this.props.onClickSolve}>Insert Solution</button>
          }
        </div>
        <div className='challenge__user-output'>
          <CodeMirror
            options={outputOptions}
            value={this.props.userOutput}
          />
        </div>
        {benchmarkResults}
        {testResults}

      </div>
    );
  }
}

ChallengePanel.defaultProps = {
  showDescription: true,
  benchmark: ''
};

ChallengePanel.propTypes = {
  title: PropTypes.string.isRequired,
  description: ImmutablePropTypes.list.isRequired,
  benchmark: PropTypes.string,
  isSessionStarted: PropTypes.bool.isRequired,
  isSessionFinished: PropTypes.bool.isRequired,
  isTimerFinished: PropTypes.bool.isRequired,
  onClickFinishSession: PropTypes.func.isRequired,
  onClickRunTests: PropTypes.func.isRequired,
  onClickSolve: PropTypes.func.isRequired,
  onClickBenchmark: PropTypes.func.isRequired,
  onClickStartChallenge: PropTypes.func.isRequired,
  userOutput: PropTypes.string.isRequired,
  benchmarkResults: ImmutablePropTypes.map.isRequired,
  testResults: ImmutablePropTypes.list.isRequired,
  editor: PropTypes.string.isRequired,<commit_msg>move profile/whiteboard btns next to solve btn<commit_after>
/* eslint no-multi-spaces: 0 */

import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';

import CodeMirror from 'react-codemirror';

const outputOptions = {
  readOnly: true,
  theme: 'monokai',
  scrollbarStyle: 'null',
  lineWrapping: true,
  mode: '',
  json: true
};

/* Component which renders the left panel containing control buttons, test
 * description and test results.*/
export default class ChallengePanel extends React.Component {
  constructor(props) {
    super(props);
    this.createMarkup = this.createMarkup.bind(this);
  }

  getOverallTestResult () {
    if (this.props.testResults.size) {
      return this.props.testResults.every(test => test.pass);
    }
    return false;
  }

  createMarkup() {
    const descr = this.props.description.join('\n');
    return { __html: descr };
  }

  renderBenchmarkResults () {
    if (!this.props.benchmarkResults.size) {
      return;
    }

    const results = this.props.benchmarkResults.toJS();

    let className;
    if (results.resultMessage === 'Your code can be made more efficient') {
      className = 'text-warning';
    }
    else if (results.resultMessage === 'Tie. Your code is fast!') {
      className = 'text-primary';
    }
    else className = 'text-success';

    return (
      <div>
        <p className='text-default'>Benchmark result:
          <span className={className}>  {results.resultMessage}</span>
        </p>
        <p className='text-muted'>{results.stockPerf}</p>
        <p className='text-muted'>{results.userPerf}</p>
      </div>
    );
  }

  /* TODO: Add limit to the number of printed tests. Improve output. */
  renderTestResults() {
    /* eslint react/no-danger: 0 */
    const results = this.props.testResults;
    const numTests = results.size;
    let testsOk = true;
    let individualTests;

    if (numTests > 0) {
      let id = 0;
      individualTests = results.map(item => {
        const result = item.pass ? 'Pass' : 'Fail';
        const className = item.pass ? 'text-success' : 'text-danger';
        testsOk = testsOk && item.pass;
        id += 1;

        // return only status of each test on Whiteboard mode
        if (this.props.editor === 'Whiteboard') {
          return <p className={className} key={id}>Status: {result}</p>;
        }

        // If test had error, format the error message here
        let msg = null;
        if (item.error !== null) {
          const innerHtml = { __html: `Error: ${item.error}` };
          msg = <span dangerouslySetInnerHTML={innerHtml} />;
        }

        return <p className={className} key={id}>Status: {result} {msg}</p>;
      });
    }
    let finalResult = testsOk ? 'All tests passed' : 'There were failing tests';
    if (numTests === 0) {
      finalResult = 'No tests run.';
    }

    return (
      <div>
        <p>Tests result: {finalResult}</p>
        {individualTests}
      </div>
    );
  }

  render() {
    let finishButton = null;
    if (this.props.isTimerFinished && !this.props.isSessionFinished) {
      finishButton = (
        <button className='btn btn-danger' onClick={this.props.onClickFinishSession}>Finish</button>
      );
    }

    const benchmarkResults = this.renderBenchmarkResults();
    const testResults = this.renderTestResults();
    const overallTestResult = this.getOverallTestResult();
    const runTestsBtnClass = (this.props.isRunningTests || this.props.isRunningBenchmark) ? 'btn btn-primary disabled' : 'btn btn-primary';
    const runBenchmarkBtnClass = (this.props.isRunningTests || this.props.isRunningBenchmark) ? 'btn btn-info disabled' : 'btn btn-info';

    /* eslint react/no-danger: 0 */
    return (
      <div className='challenge-panel'>
        <div className='challenge__title'>{this.props.title}</div>
        {this.props.showDescription &&
        <div className='challenge__description' dangerouslySetInnerHTML={this.createMarkup()} />
        }
        <div className='challenge__buttons'>
          {!this.props.isSessionStarted &&
            <button className='btn btn-success' onClick={this.props.onClickStartChallenge}>Start</button>
          }
          {(!this.props.isSessionStarted || this.props.mode === 'Practice') &&
            <button className='btn btn-primary' onClick={this.props.onModalOpen}>Menu</button>
          }
          {this.props.isSessionStarted &&
            <button className={runTestsBtnClass} onClick={this.props.onClickRunTests}>Run tests</button>
          }
          {this.props.isSessionStarted &&
            overallTestResult &&
            this.props.benchmark !== '' &&
            <button className={runBenchmarkBtnClass} onClick={this.props.onClickBenchmark}>Benchmark</button>
          }

          {finishButton}
        </div>
        <div className='challenge__buttons'>

          <button
            className='btn btn-default'
            onClick={this.props.onClickShowHideProfile}
          >
            {this.props.isProfileShown &&
            'Hide Profile'
            }
            {!this.props.isProfileShown &&
            'Show Profile'
            }
          </button>

          <input
            className='btn btn-default'
            type='button'
            onClick={this.props.onChangeEditor}
            value={this.props.editor === 'Normal' ? 'Whiteboard' : 'Normal'}
          />
          {this.props.isSessionStarted &&
            <button className='btn btn-warning' onClick={this.props.onClickSolve}>Insert Solution</button>
          }
        </div>
        <div className='challenge__user-output'>
          <CodeMirror
            options={outputOptions}
            value={this.props.userOutput}
          />
        </div>
        {benchmarkResults}
        {testResults}

      </div>
    );
  }
}

ChallengePanel.defaultProps = {
  showDescription: true,
  benchmark: ''
};

ChallengePanel.propTypes = {
  title: PropTypes.string.isRequired,
  description: ImmutablePropTypes.list.isRequired,
  benchmark: PropTypes.string,
  isSessionStarted: PropTypes.bool.isRequired,
  isSessionFinished: PropTypes.bool.isRequired,
  isTimerFinished: PropTypes.bool.isRequired,
  onClickFinishSession: PropTypes.func.isRequired,
  onClickRunTests: PropTypes.func.isRequired,
  onClickShowHideProfile: PropTypes.func.isRequired,
  isProfileShown: PropTypes.bool.isRequired,
  onChangeEditor: PropTypes.func.isRequired,
  onClickSolve: PropTypes.func.isRequired,
  onClickBenchmark: PropTypes.func.isRequired,
  onClickStartChallenge: PropTypes.func.isRequired,
  userOutput: PropTypes.string.isRequired,
  benchmarkResults: ImmutablePropTypes.map.isRequired,
  testResults: ImmutablePropTypes.list.isRequired,
  editor: PropTypes.string.isRequired,
{'fraction_non_alphanumeric': 0.12684251357641582, 'fraction_numerical': 0.0010861132660977503, 'mean_word_length': 2.7704007019596375, 'pattern_counts': {'":': 0, '<': 92, '<?xml version=': 0, '>': 98, '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': '2556357', 'n_tokens_mistral': 3805, 'n_tokens_neox': 3739, 'n_words': 769}