<commit_before>import {compose, curry, identity, filter, map,
  range, repeat, transduce} from 'ramda';
import React from 'react'; // eslint-disable-line
import {connect} from 'react-redux';
import {playNote, stopNote} from '../../noteController';
import store from '../../store';
import {activePatternCellClick,
        updateActivePatternActivePosition} from '../../actions';
import {forEachIndexed, mapIndexed} from '../../tools/indexedIterators';
import Pattern from '../organisms/Pattern';
import PlayButton from '../atoms/PlayButton';
import Navigation from '../organisms/Navigation';
import pitchFromScaleIndex from '../../tools/pitchFromScaleIndex';
import PatternOptions from '../organisms/PatternOptions';
import noteNameFromPitch from '../../tools/noteNameFromPitch';
import {noteExists} from '../../reducers/patterns';

const playStopSubject = new Rx.Subject();

const stopAllNotes = forEachIndexed((row, rowIndex) =>
  forEachIndexed((cell, cellIndex) => stopNote({id: `pattern-editor-${rowIndex}${cellIndex}`}),
                 row));

const onPlay = dispatch =>
  Rx.Observable
    .generateWithRelativeTime(0,
                              () => true,
                              x => x + 1,
                              x => x,
                              () => 60000 / store.getState().bpm)
    .takeUntil(playStopSubject)
    .map(count => {
      const {activePatternIndex, patterns, scale} = store.getState();
      const {notes, patternLength} = patterns[activePatternIndex];
      return {notes, position: count % patternLength, scale};
    })
    .do(({position}) => dispatch(updateActivePatternActivePosition(position)))
    .do(compose(stopAllNotes, x => x.notes))
    .subscribe(({notes, position, scale}) =>
      transduce(compose(mapIndexed((row, rowIndex) => ({id: `pattern-editor-${rowIndex}${position}`,
                                                        instrument: store.getState().patterns.patterns[store.getState().patterns.activePattern].instrument,
                                                        pitch: pitchFromScaleIndex(scale.scales[scale.scaleName], notes.length - 1 - rowIndex),
                                                        selected: row[position].selected})),
                                   filter(({selected}) => selected),
                                   map(playNote)),
                            () => {},
                            null,
                            notes));

const onStop = dispatch => {
  const {activePatternIndex, patterns} = store.getState();
  const {notes} = patterns[activePatternIndex];
  stopAllNotes(notes);
  playStopSubject.onNext();
  dispatch(updateActivePatternActivePosition(null));
};

const yLabel = curry((scale, length, rootNote, i) =>
  noteNameFromPitch(pitchFromScaleIndex(scale.scales[scale.scaleName],
                                        length - i - 1) + rootNote));

export default connect(identity)(({activePatternIndex, dispatch, instrument, patterns, rootNote, scale}) => {
  const activePattern = patterns[activePatternIndex];
  const {activePosition, patternLength, notes} = activePattern;
  const createEmptyPatternData = compose(map(range(0)),
                                        length => repeat(length, length));
  const patternData = mapIndexed((x, i) => map(j => ({active: j === activePosition,
                                                      selected: noteExists(notes, i, j)}),
                                               x),
                                 createEmptyPatternData(patternLength));
  const onClick = x => y => () => dispatch(activePatternCellClick({x, y}));
  return <div>
    <Navigation />
    <Pattern patternData={patternData}<commit_msg>stop note reimplemented for pattern<commit_after>import {compose, curry, identity, filter, forEach, map,
  range, repeat, transduce} from 'ramda';
import React from 'react'; // eslint-disable-line
import {connect} from 'react-redux';
import {playNote, stopNote} from '../../noteController';
import store from '../../store';
import {activePatternCellClick,
        updateActivePatternActivePosition} from '../../actions';
import {mapIndexed} from '../../tools/indexedIterators';
import Pattern from '../organisms/Pattern';
import PlayButton from '../atoms/PlayButton';
import Navigation from '../organisms/Navigation';
import pitchFromScaleIndex from '../../tools/pitchFromScaleIndex';
import PatternOptions from '../organisms/PatternOptions';
import noteNameFromPitch from '../../tools/noteNameFromPitch';
import {noteExists} from '../../reducers/patterns';

const playStopSubject = new Rx.Subject();

const stopAllNotes = forEach(({x, y}) => stopNote({id: `pattern-editor-${x}${y}`}));

const onPlay = dispatch =>
  Rx.Observable
    .generateWithRelativeTime(0,
                              () => true,
                              x => x + 1,
                              x => x,
                              () => 60000 / store.getState().bpm)
    .takeUntil(playStopSubject)
    .map(count => {
      const {activePatternIndex, patterns, scale} = store.getState();
      const {notes, patternLength} = patterns[activePatternIndex];
      return {notes, patternLength, position: count % patternLength, scale};
    })
    .do(({position}) => dispatch(updateActivePatternActivePosition(position)))
    .do(compose(stopAllNotes, ({notes}) => notes))
    .subscribe(({notes, patternLength, position, scale}) =>
      transduce(compose(filter(({y}) => y === position),
                        map(({x, y}) => ({id: `pattern-editor-${x}${y}`,
                                          instrument: store.getState().patterns[store.getState().activePatternIndex].instrument,
                                          pitch: pitchFromScaleIndex(scale.scales[scale.scaleName], patternLength - 1 - x)})),
                        map(playNote)),
                () => {},
                null,
                notes));

const onStop = dispatch => {
  const {activePatternIndex, patterns} = store.getState();
  const {notes} = patterns[activePatternIndex];
  stopAllNotes(notes);
  playStopSubject.onNext();
  dispatch(updateActivePatternActivePosition(null));
};

const yLabel = curry((scale, length, rootNote, i) =>
  noteNameFromPitch(pitchFromScaleIndex(scale.scales[scale.scaleName],
                                        length - i - 1) + rootNote));

export default connect(identity)(({activePatternIndex, dispatch, instrument, patterns, rootNote, scale}) => {
  const activePattern = patterns[activePatternIndex];
  const {activePosition, patternLength, notes} = activePattern;
  const createEmptyPatternData = compose(map(range(0)),
                                        length => repeat(length, length));
  const patternData = mapIndexed((x, i) => map(j => ({active: j === activePosition,
                                                      selected: noteExists(notes, i, j)}),
                                               x),
                                 createEmptyPatternData(patternLength));
  const onClick = x => y => () => dispatch(activePatternCellClick({x, y}));
  return <div>
    <Navigation />
    <Pattern patternData={patternData}
{'fraction_non_alphanumeric': 0.13782542113323124, 'fraction_numerical': 0.0027843519420854795, 'mean_word_length': 2.377527033380348, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4735011', 'n_tokens_mistral': 1806, 'n_tokens_neox': 1763, 'n_words': 415}