<commit_before>import React from "react"
import Bacon from "baconjs"
import _ from "underscore"

import Position from "./Position"
import Board from "./Board"
import tools from "./tools"

import styles from "./style.css"

export default class SnakeGame extends React.Component {
    static propTypes = {
        boardSize: React.PropTypes.instanceOf(Position).isRequired,
    }

    static defaultProps = {
        initialSnakeDirection: new Position(0, 1),
        initialSnakeLength: 3,
        initialSnakePosition: new Position(0, 0),
    }

    state = {
        snakePositions: [],
        fruitPositions: [Position.randomPosition(this.props.boardSize)],
        score: 0,
    }

    constructor(props) {
        super(props)
        const keys = Bacon.fromEvent(document.body, "keyup").map('.keyCode')
        const lefts = keys.filter(x => x === 37)
        const rights = keys.filter(x => x === 39)
        const ticks = Bacon.interval(100)
        this.input = { lefts: lefts, rights: rights, ticks: ticks }
    }

    componentDidMount() {
        const headPositions = this.snakeHeadPositions()
        headPositions
            .scan([], (buf, x) => _.last(_.union(buf, [x]), this.props.initialSnakeLength + this.state.score))
            .onValue(snake => this.setState({ snakePositions: snake }))

        const fruitEatenEvents = headPositions.filter(head => tools.contains(this.state.fruitPositions, head))
        fruitEatenEvents.onValue(() => this.setState({ score: this.state.score + 1 }))

        fruitEatenEvents.map(() => Position.randomPosition(this.props.boardSize))
                        .onValue(position => this.setState({ fruitPositions: [position] }))
    }

    snakeHeadPositions() {
        const leftsMappedToRotations = this.input.lefts.map(() => Position.rotateLeft)
        const rightsMappedToRotations = this.input.rights.map(() => Position.rotateRight)
        const actions = leftsMappedToRotations.merge(rightsMappedToRotations)

        const directions = actions.scan(this.props.initialSnakeDirection, (x, f) => f(x))

        return directions
            .sampledBy(this.input.ticks)
            .scan(this.props.initialSnakePosition, (x, y) => x.add(y).mod(this.props.boardSize))
    }

    render() {
        return (
            <div className={styles.game}>
                <div id={styles.log}>Score: {this.state.score}</div>
                <Board size={this.props.boardSize} snakePositions={this.state.snakePositions} fruitPositions={this.state.fruitPositions}/>
            </div>
        )
    }
}<commit_msg>changed constructor into inputStreams method<commit_after>import React from "react"
import Bacon from "baconjs"
import _ from "underscore"

import Position from "./Position"
import Board from "./Board"
import tools from "./tools"

import styles from "./style.css"

export default class SnakeGame extends React.Component {
    static propTypes = {
        boardSize: React.PropTypes.instanceOf(Position).isRequired,
    }

    static defaultProps = {
        initialSnakeDirection: new Position(0, 1),
        initialSnakeLength: 3,
        initialSnakePosition: new Position(0, 0),
    }

    state = {
        snakePositions: [],
        fruitPositions: [Position.randomPosition(this.props.boardSize)],
        score: 0,
    }

    inputStreams() {
        const keys = Bacon.fromEvent(document.body, "keyup").map('.keyCode')
        const lefts = keys.filter(x => x === 37)
        const rights = keys.filter(x => x === 39)
        const ticks = Bacon.interval(100)
        return { lefts: lefts, rights: rights, ticks: ticks }
    }

    componentDidMount() {
        const headPositions = this.snakeHeadPositions()
        headPositions
            .scan([], (buf, x) => _.last(_.union(buf, [x]), this.props.initialSnakeLength + this.state.score))
            .onValue(snake => this.setState({ snakePositions: snake }))

        const fruitEatenEvents = headPositions.filter(head => tools.contains(this.state.fruitPositions, head))
        fruitEatenEvents.onValue(() => this.setState({ score: this.state.score + 1 }))

        fruitEatenEvents.map(() => Position.randomPosition(this.props.boardSize))
                        .onValue(position => this.setState({ fruitPositions: [position] }))
    }

    snakeHeadPositions() {
        const { lefts, rights, ticks } = this.inputStreams()
        const leftsMappedToRotations = lefts.map(() => Position.rotateLeft)
        const rightsMappedToRotations = rights.map(() => Position.rotateRight)
        const actions = leftsMappedToRotations.merge(rightsMappedToRotations)

        const directions = actions.scan(this.props.initialSnakeDirection, (x, f) => f(x))

        return directions
            .sampledBy(ticks)
            .scan(this.props.initialSnakePosition, (x, y) => x.add(y).mod(this.props.boardSize))
    }

    render() {
        return (
            <div className={styles.game}>
                <div id={styles.log}>Score: {this.state.score}</div>
                <Board size={this.props.boardSize} snakePositions={this.state.snakePositions} fruitPositions={this.state.fruitPositions}/>
            </div>
        )
    }
}
{'fraction_non_alphanumeric': 0.1297443841982959, 'fraction_numerical': 0.005422153369481022, 'mean_word_length': 2.761835396941005, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 37, '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': '5663539', 'n_tokens_mistral': 1548, 'n_tokens_neox': 1484, 'n_words': 308}