<commit_before>import { Observable } from 'rx';
import { push } from 'react-router-redux';
import types from './types';
import {
  showChallengeComplete,
  moveToNextChallenge,
  updateCurrentChallenge
} from './actions';
import {
  createErrorObservable,
  makeToast,
  updatePoints
} from '../../../redux/actions';

import { getNextChallenge } from '../utils';
import { challengeSelector } from './selectors';

import { postJSON$ } from '../../../../utils/ajax-stream';

function completedChallenge(state) {
  let body;
  let isSignedIn = false;
  try {
    const {
      challenge: { id }
    } = challengeSelector(state);
    const {
      app: { isSignedIn: _isSignedId, csrfToken },
      challengesApp: { files }
    } = state;
    isSignedIn = _isSignedId;
    body = {
      id,
      _csrf: csrfToken,
      files
    };
  } catch (err) {
    return createErrorObservable(err);
  }
  const saveChallenge$ = postJSON$('/modern-challenge-completed', body)
    .retry(3)
    .flatMap(({ alreadyCompleted, points }) => {
      return Observable.of(
        makeToast({
            message:
              'Challenge saved.' +
              (alreadyCompleted ? '' : ' First time Completed!'),
            title: 'Saved',
            type: 'info'
        }),
        updatePoints(points)
      );
    })
    .catch(createErrorObservable);

  const challengeCompleted$ = Observable.of(
    moveToNextChallenge(),
    makeToast({
      title: 'Congratulations!',
      message: isSignedIn ? ' Saving...' : 'Moving on to next challenge',
      type: 'success'
    })
  );
  return Observable.merge(saveChallenge$, challengeCompleted$);
}

export default function completionSaga(actions$, getState) {
  return actions$
    .filter(({ type }) => (
      type === types.checkChallenge ||
      type === types.submitChallenge ||
      type === types.moveToNextChallenge
    ))
    .flatMap(({ type }) => {
      const state = getState();
      const { tests } = state.challengesApp;
      if (tests.length > 1 && tests.every(test => test.pass && !test.err)) {
        if (type === types.checkChallenge) {
          return Observable.of(
            showChallengeComplete()
          );
        }

        if (type === types.submitChallenge) {
          return completedChallenge(state);
        }

        if (type === types.moveToNextChallenge) {
          const nextChallenge = getNextChallenge(
            state.challengesApp.challenge,
            state.entities,
            state.challengesApp.superBlocks
          );
          return Observable.of(
            updateCurrentChallenge(nextChallenge),
            push(`/challenges/${nextChallenge.dashedName}`)
          );
        }
      }
      return Observable.just(makeToast({
        message: 'Not all tests are passing',
        title: 'Not quite there',
        type: 'info'
      }));
    });
}<commit_msg>Fix test check typo Fix punctuation<commit_after>import { Observable } from 'rx';
import { push } from 'react-router-redux';
import types from './types';
import {
  showChallengeComplete,
  moveToNextChallenge,
  updateCurrentChallenge
} from './actions';
import {
  createErrorObservable,
  makeToast,
  updatePoints
} from '../../../redux/actions';

import { getNextChallenge } from '../utils';
import { challengeSelector } from './selectors';

import { postJSON$ } from '../../../../utils/ajax-stream';

function completedChallenge(state) {
  let body;
  let isSignedIn = false;
  try {
    const {
      challenge: { id }
    } = challengeSelector(state);
    const {
      app: { isSignedIn: _isSignedId, csrfToken },
      challengesApp: { files }
    } = state;
    isSignedIn = _isSignedId;
    body = {
      id,
      _csrf: csrfToken,
      files
    };
  } catch (err) {
    return createErrorObservable(err);
  }
  const saveChallenge$ = postJSON$('/modern-challenge-completed', body)
    .retry(3)
    .flatMap(({ alreadyCompleted, points }) => {
      return Observable.of(
        makeToast({
            message:
              'Challenge saved.' +
              (alreadyCompleted ? '' : ' First time Completed!'),
            title: 'Saved',
            type: 'info'
        }),
        updatePoints(points)
      );
    })
    .catch(createErrorObservable);

  const challengeCompleted$ = Observable.of(
    moveToNextChallenge(),
    makeToast({
      title: 'Congratulations!',
      message: isSignedIn ? ' Saving...' : 'Moving on to next challenge.',
      type: 'success'
    })
  );
  return Observable.merge(saveChallenge$, challengeCompleted$);
}

export default function completionSaga(actions$, getState) {
  return actions$
    .filter(({ type }) => (
      type === types.checkChallenge ||
      type === types.submitChallenge ||
      type === types.moveToNextChallenge
    ))
    .flatMap(({ type }) => {
      const state = getState();
      const { tests } = state.challengesApp;
      if (tests.length > 0 && tests.every(test => test.pass && !test.err)) {
        if (type === types.checkChallenge) {
          return Observable.of(
            showChallengeComplete()
          );
        }

        if (type === types.submitChallenge) {
          return completedChallenge(state);
        }

        if (type === types.moveToNextChallenge) {
          const nextChallenge = getNextChallenge(
            state.challengesApp.challenge,
            state.entities,
            state.challengesApp.superBlocks
          );
          return Observable.of(
            updateCurrentChallenge(nextChallenge),
            push(`/challenges/${nextChallenge.dashedName}`)
          );
        }
      }
      return Observable.just(makeToast({
        message: 'Not all tests are passing, yet.',
        title: 'Almost There!',
        type: 'info'
      }));
    });
}
{'fraction_non_alphanumeric': 0.13351829374024624, 'fraction_numerical': 0.000693601525923357, 'mean_word_length': 2.262443438914027, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, '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': '7482696', 'n_tokens_mistral': 1733, 'n_tokens_neox': 1658, 'n_words': 361}