<commit_before>const {h, Component} = require('preact')
const classNames = require('classnames')
const {BoundedGoban} = require('@sabaki/shudan')
const {remote} = require('electron')

const helper = require('../modules/helper')
const setting = remote.require('./setting')

class Goban extends Component {
    constructor(props) {
        super()

        this.handleVertexMouseUp = this.handleVertexMouseUp.bind(this)
        this.handleVertexMouseDown = this.handleVertexMouseDown.bind(this)
        this.handleVertexMouseMove = this.handleVertexMouseMove.bind(this)
        this.handleVertexMouseEnter = this.handleVertexMouseEnter.bind(this)
        this.handleVertexMouseLeave = this.handleVertexMouseLeave.bind(this)
    }

    componentDidMount() {
        document.addEventListener('mouseup', () => {
            this.mouseDown = false

            if (this.state.temporaryLine)
                this.setState({temporaryLine: null})
        })

        // Resize board when window is resizing

        window.addEventListener('resize', () => {
            this.componentDidUpdate()
            this.setState({})
        })

        this.componentDidUpdate()
    }

    componentDidUpdate(prevProps) {
        if (!this.element || !this.element.parentElement) return

        let {offsetWidth: maxWidth, offsetHeight: maxHeight} = this.element.parentElement

        if (maxWidth !== this.state.maxWidth || maxHeight !== this.state.maxHeight) {
            this.setState({maxWidth, maxHeight})
        }

        if (prevProps == null || prevProps.playVariation !== this.props.playVariation) {
            if (this.props.playVariation != null) {
                let {sign, variation, removeCurrent} = this.props.playVariation

                this.stopPlayingVariation()
                this.playVariation(sign, variation, removeCurrent)
            } else {
                this.stopPlayingVariation()
            }
        }
    }

    handleVertexMouseDown(evt, vertex) {
        this.mouseDown = true
        this.startVertex = vertex
    }

    handleVertexMouseUp(evt, vertex) {
        if (!this.mouseDown) return

        let {onVertexClick = helper.noop, onLineDraw = helper.noop} = this.props

        this.mouseDown = false
        evt.vertex = vertex
        evt.line = this.state.temporaryLine

        if (evt.x == null) evt.x = evt.clientX
        if (evt.y == null) evt.y = evt.clientY

        if (evt.line) {
            onLineDraw(evt)
        } else {
            this.stopPlayingVariation()
            onVertexClick(evt)
        }

        this.setState({clicked: true})
        setTimeout(() => this.setState({clicked: false}), 200)
    }

    handleVertexMouseMove(evt, vertex) {
        let {drawLineMode, onVertexMouseMove = helper.noop} = this.props

        onVertexMouseMove(Object.assign(evt, {
            mouseDown: this.mouseDown,
            startVertex: this.startVertex,
            vertex
        }))

        if (!!drawLineMode && evt.mouseDown && evt.button === 0) {
            let temporaryLine = {v1: evt.startVertex, v2: evt.vertex}

            if (!helper.equals(temporaryLine, this.state.temporaryLine)) {
                this.setState({temporaryLine})
            }
        }
    }

    handleVertexMouseEnter(evt, vertex) {
        if (this.props.analysis == null) return

        let {sign, variation} = this.props.analysis.find(x => helper.vertexEquals(x.vertex, vertex)) || {}
        if (variation == null) return

        this.playVariation(sign, variation)
    }

    handleVertexMouseLeave(evt, vertex) {
        this.stopPlayingVariation()
    }

    playVariation(sign, variation, removeCurrent = false) {
        clearInterval(this.variationIntervalId)

        this.variationIntervalId = setInterval(() => {
            this.setState(({variationIndex}) => ({
                variation,
                variationSign: sign,
                variationRemoveCurrent: removeCurrent,
                variationIndex: variationIndex + 1
            }))
        }, setting.get('board.variation_replay_interval'))
    }

    stopPlayingVariation() {
        if (this.variationIntervalId == null) return

        clearInterval(this.variationIntervalId)
        this.variationIntervalId = null

        this.setState({
            variation: null,
            variationIndex: -1
        })
    }

    render({
        board,
        paintMap,
        analysis,
        highlightVertices = [],
        dimmedStones = [],

        crosshair = false,
        showCoordinates = false,
        showMoveColorization = true,<commit_msg>Fix autoplaying variation not working on first try<commit_after>const {h, Component} = require('preact')
const classNames = require('classnames')
const {BoundedGoban} = require('@sabaki/shudan')
const {remote} = require('electron')

const helper = require('../modules/helper')
const setting = remote.require('./setting')

class Goban extends Component {
    constructor(props) {
        super()

        this.handleVertexMouseUp = this.handleVertexMouseUp.bind(this)
        this.handleVertexMouseDown = this.handleVertexMouseDown.bind(this)
        this.handleVertexMouseMove = this.handleVertexMouseMove.bind(this)
        this.handleVertexMouseEnter = this.handleVertexMouseEnter.bind(this)
        this.handleVertexMouseLeave = this.handleVertexMouseLeave.bind(this)
    }

    componentDidMount() {
        document.addEventListener('mouseup', () => {
            this.mouseDown = false

            if (this.state.temporaryLine)
                this.setState({temporaryLine: null})
        })

        // Resize board when window is resizing

        window.addEventListener('resize', () => {
            this.componentDidUpdate()
            this.setState({})
        })

        this.componentDidUpdate()
    }

    componentDidUpdate(prevProps) {
        if (!this.element || !this.element.parentElement) return

        let {offsetWidth: maxWidth, offsetHeight: maxHeight} = this.element.parentElement

        if (maxWidth !== this.state.maxWidth || maxHeight !== this.state.maxHeight) {
            this.setState({maxWidth, maxHeight})
        }

        if (prevProps == null || prevProps.playVariation !== this.props.playVariation) {
            if (this.props.playVariation != null) {
                let {sign, variation, removeCurrent} = this.props.playVariation

                this.stopPlayingVariation()
                this.playVariation(sign, variation, removeCurrent)
            } else {
                this.stopPlayingVariation()
            }
        }
    }

    handleVertexMouseDown(evt, vertex) {
        this.mouseDown = true
        this.startVertex = vertex
    }

    handleVertexMouseUp(evt, vertex) {
        if (!this.mouseDown) return

        let {onVertexClick = helper.noop, onLineDraw = helper.noop} = this.props

        this.mouseDown = false
        evt.vertex = vertex
        evt.line = this.state.temporaryLine

        if (evt.x == null) evt.x = evt.clientX
        if (evt.y == null) evt.y = evt.clientY

        if (evt.line) {
            onLineDraw(evt)
        } else {
            this.stopPlayingVariation()
            onVertexClick(evt)
        }

        this.setState({clicked: true})
        setTimeout(() => this.setState({clicked: false}), 200)
    }

    handleVertexMouseMove(evt, vertex) {
        let {drawLineMode, onVertexMouseMove = helper.noop} = this.props

        onVertexMouseMove(Object.assign(evt, {
            mouseDown: this.mouseDown,
            startVertex: this.startVertex,
            vertex
        }))

        if (!!drawLineMode && evt.mouseDown && evt.button === 0) {
            let temporaryLine = {v1: evt.startVertex, v2: evt.vertex}

            if (!helper.equals(temporaryLine, this.state.temporaryLine)) {
                this.setState({temporaryLine})
            }
        }
    }

    handleVertexMouseEnter(evt, vertex) {
        if (this.props.analysis == null) return

        let {sign, variation} = this.props.analysis.find(x => helper.vertexEquals(x.vertex, vertex)) || {}
        if (variation == null) return

        this.playVariation(sign, variation)
    }

    handleVertexMouseLeave(evt, vertex) {
        this.stopPlayingVariation()
    }

    playVariation(sign, variation, removeCurrent = false) {
        clearInterval(this.variationIntervalId)

        this.variationIntervalId = setInterval(() => {
            this.setState(({variationIndex = -1}) => ({
                variation,
                variationSign: sign,
                variationRemoveCurrent: removeCurrent,
                variationIndex: variationIndex + 1
            }))
        }, setting.get('board.variation_replay_interval'))
    }

    stopPlayingVariation() {
        if (this.variationIntervalId == null) return

        clearInterval(this.variationIntervalId)
        this.variationIntervalId = null

        this.setState({
            variation: null,
            variationIndex: -1
        })
    }

    render({
        board,
        paintMap,
        analysis,
        highlightVertices = [],
        dimmedStones = [],

        crosshair = false,
        showCoordinates = false,
        showMoveColorization = true,
{'fraction_non_alphanumeric': 0.11082138200782268, 'fraction_numerical': 0.0018470230334637113, 'mean_word_length': 2.1818181818181817, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, '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': '5736101', 'n_tokens_mistral': 2564, 'n_tokens_neox': 2512, 'n_words': 459}