<commit_before>/*
 * Copyright (C) 2012-2022  Online-Go.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import * as React from "react";
import { pgettext, _ } from "translate";
import { openModal, Modal } from "Modal";
import { Goban } from "goban";
import { Player } from "Player";

interface Events {}

interface GameLinkModalProperties {
    goban: Goban;
}

export class GameLinkModal extends Modal<Events, GameLinkModalProperties, {}> {
    constructor(props) {
        super(props);
    }

    render() {
        const goban = this.props.goban;
        let png_url: string;
        let sgf_url: string;
        if (goban.game_id) {
            sgf_url = `${window.location.protocol}//${window.location.hostname}/api/v1/games/${goban.game_id}/sgf`;
            png_url = `${window.location.protocol}//${window.location.hostname}/api/v1/games/${goban.game_id}/png`;
        } else {
            sgf_url = `${window.location.protocol}//${window.location.hostname}/api/v1/reviews/${goban.review_id}/sgf`;
            png_url = `${window.location.protocol}//${window.location.hostname}/api/v1/reviews/${goban.review_id}/png`;
        }

        return (
            <div className="Modal GameLinkModal" ref="modal">
                <div className="header">
                    <div>
                        <h2>{goban.engine.config.game_name}</h2>
                        <h3>
                            <Player
                                disableCacheUpdate
                                icon
                                rank
                                user={goban.engine.config.players.black}
                            />{" "}
                            {_("vs.")}{" "}
                            <Player
                                disableCacheUpdate
                                icon
                                rank
                                user={goban.engine.config.players.white}
                            />
                        </h3>
                    </div>
                </div>
                <div className="body">
                    <div className="GameLink-kv">
                        <a href={"" + window.location} target="_blank">
                            <i className="fa fa-link" />
                        </a>
                        <span>
                            {
                                goban.game_id
                                    ? _("Game") /* Translators: Link to game */
                                    : _("Review") /* Translators: Link to review */
                            }
                            :{" "}
                        </span>
                        <input
                            type="text"
                            value={"" + window.location}
                            onClick={(ev) => (ev.target as HTMLInputElement).select()}
                            readOnly
                        />
                    </div>

                    <div className="GameLink-kv">
                        <a href={sgf_url} target="_blank">
                            <i className="fa fa-link" />
                        </a>
                        <span>{_("SGF")}: </span>
                        <input
                            type="text"
                            value={sgf_url}
                            onClick={(ev) => (ev.target as HTMLInputElement).select()}
                            readOnly
                        />
                    </div>

                    <div className="GameLink-kv">
                        <a href={png_url} target="_blank">
                            <i className="fa fa-link" />
                        </a>
                        <span>{_("PNG")}: </span>
                        <input
                            type="text"
                            value={png_url}
                            onClick={(ev) => (ev.target as HTMLInputElement).select()}
                            readOnly
                        />
                    </div>

                    {goban.game_id && <AnimatedPngCreator goban={goban} />}
                </div>
                <div className="buttons">
                    <button onClick={this.close}>{_("Close")}</button>
                </div>
            </div>
        );
    }
}

function AnimatedPngCreator({ goban }: { goban: Goban }): JSX.Element {
    const MAX_MOVES = 30;

    const engine = goban.engine;
    const [from_move, setFromMove] = React.useState(Math.max(engine?.getMoveNumber() - 10, 1));
    const [to_move, setToMove] = React.useState(Math.max(engine?.getMoveNumber(), 1));
    const [frame_delay, setFrameDelay] = React.useState(1500);
    const [preview_url, setPreviewUrl] = React.useState("");

    const url =
        `${window.location.protocol}//${window.location.hostname}` +
        `/api/v1/games/${goban.game_id}/apng?from=${from_move}&to=${to_move}&frame_delay=${frame_delay}`;

    return (
        <div className="AnimatedPngCreator">
            <div className="GameLink-kv">
                <a href={url} target="_blank">
                    <i className="fa fa-link" />
                </a>
                <span style={{ textAlign: "right" }}>{_("Animated")}: </span>
                <input
                    type="text"
                    value={url}
                    onClick={(ev) => (ev.target as HTMLInputElement).select()}
                    readOnly
                />
            </div>

            <div className="range-row">
                <label htmlFor="from">
                    {pgettext("The starting move number of an animated png", "From move")}
                </label>
                <input
                    id="from"
                    name="from"
                    type="range"
                    min={1}
                    max={engine.getMoveNumber()}
                    value={from_move}
                    onChange={(ev) => {
                        const new_from_move = parseInt(ev.target.value);
                        setFromMove(new_from_move);
                        setToMove(
                            Math.max(new_from_move, Math.min(to_move, new_from_move + MAX_MOVES)),
                        );
                    }}
                />
                <span>{from_move}</span>
            </div>

            <div className="range-row">
                <label htmlFor="to">
                    {pgettext("The ending move number of an animated png", "To move")}
                </label>
                <input
                    id="to"
                    name="to"
                    type="range"
                    min={1}
                    max={engine.getMoveNumber()}
                    value={to_move}
                    onChange={(ev) => {
                        const new_to_move = parseInt(ev.target.value);
                        setToMove(new_to_move);
                        setFromMove(<commit_msg>Provide filename looking path for apngs, fix max move number limiter in apng creator<commit_after>/*
 * Copyright (C) 2012-2022  Online-Go.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import * as React from "react";
import { pgettext, _ } from "translate";
import { openModal, Modal } from "Modal";
import { Goban } from "goban";
import { Player } from "Player";

interface Events {}

interface GameLinkModalProperties {
    goban: Goban;
}

export class GameLinkModal extends Modal<Events, GameLinkModalProperties, {}> {
    constructor(props) {
        super(props);
    }

    render() {
        const goban = this.props.goban;
        let png_url: string;
        let sgf_url: string;
        if (goban.game_id) {
            sgf_url = `${window.location.protocol}//${window.location.hostname}/api/v1/games/${goban.game_id}/sgf`;
            png_url = `${window.location.protocol}//${window.location.hostname}/api/v1/games/${goban.game_id}/png`;
        } else {
            sgf_url = `${window.location.protocol}//${window.location.hostname}/api/v1/reviews/${goban.review_id}/sgf`;
            png_url = `${window.location.protocol}//${window.location.hostname}/api/v1/reviews/${goban.review_id}/png`;
        }

        return (
            <div className="Modal GameLinkModal" ref="modal">
                <div className="header">
                    <div>
                        <h2>{goban.engine.config.game_name}</h2>
                        <h3>
                            <Player
                                disableCacheUpdate
                                icon
                                rank
                                user={goban.engine.config.players.black}
                            />{" "}
                            {_("vs.")}{" "}
                            <Player
                                disableCacheUpdate
                                icon
                                rank
                                user={goban.engine.config.players.white}
                            />
                        </h3>
                    </div>
                </div>
                <div className="body">
                    <div className="GameLink-kv">
                        <a href={"" + window.location} target="_blank">
                            <i className="fa fa-link" />
                        </a>
                        <span>
                            {
                                goban.game_id
                                    ? _("Game") /* Translators: Link to game */
                                    : _("Review") /* Translators: Link to review */
                            }
                            :{" "}
                        </span>
                        <input
                            type="text"
                            value={"" + window.location}
                            onClick={(ev) => (ev.target as HTMLInputElement).select()}
                            readOnly
                        />
                    </div>

                    <div className="GameLink-kv">
                        <a href={sgf_url} target="_blank">
                            <i className="fa fa-link" />
                        </a>
                        <span>{_("SGF")}: </span>
                        <input
                            type="text"
                            value={sgf_url}
                            onClick={(ev) => (ev.target as HTMLInputElement).select()}
                            readOnly
                        />
                    </div>

                    <div className="GameLink-kv">
                        <a href={png_url} target="_blank">
                            <i className="fa fa-link" />
                        </a>
                        <span>{_("PNG")}: </span>
                        <input
                            type="text"
                            value={png_url}
                            onClick={(ev) => (ev.target as HTMLInputElement).select()}
                            readOnly
                        />
                    </div>

                    {goban.game_id && <AnimatedPngCreator goban={goban} />}
                </div>
                <div className="buttons">
                    <button onClick={this.close}>{_("Close")}</button>
                </div>
            </div>
        );
    }
}

function AnimatedPngCreator({ goban }: { goban: Goban }): JSX.Element {
    const engine = goban.engine;
    const MAX_MOVES = 30;
    const NUM_MOVES = engine?.last_official_move.move_number || 1;
    const [from_move, setFromMove] = React.useState(Math.max(NUM_MOVES - 10, 1));
    const [to_move, setToMove] = React.useState(Math.max(NUM_MOVES, 1));
    const [frame_delay, setFrameDelay] = React.useState(1500);
    const [preview_url, setPreviewUrl] = React.useState("");

    const url =
        `${window.location.protocol}//${window.location.hostname}` +
        `/api/v1/games/${goban.game_id}/apng/${goban.game_id}-${from_move}-${to_move}-${frame_delay}.png?from=${from_move}&to=${to_move}&frame_delay=${frame_delay}`;

    return (
        <div className="AnimatedPngCreator">
            <div className="GameLink-kv">
                <a href={url} target="_blank">
                    <i className="fa fa-link" />
                </a>
                <span style={{ textAlign: "right" }}>{_("Animated")}: </span>
                <input
                    type="text"
                    value={url}
                    onClick={(ev) => (ev.target as HTMLInputElement).select()}
                    readOnly
                />
            </div>

            <div className="range-row">
                <label htmlFor="from">
                    {pgettext("The starting move number of an animated png", "From move")}
                </label>
                <input
                    id="from"
                    name="from"
                    type="range"
                    min={1}
                    max={NUM_MOVES}
                    value={from_move}
                    onChange={(ev) => {
                        const new_from_move = parseInt(ev.target.value);
                        setFromMove(new_from_move);
                        setToMove(
                            Math.max(new_from_move, Math.min(to_move, new_from_move + MAX_MOVES)),
                        );
                    }}
                />
                <span>{from_move}</span>
            </div>

            <div className="range-row">
                <label htmlFor="to">
                    {pgettext("The ending move number of an animated png", "To move")}
                </label>
                <input
                    id="to"
                    name="to"
                    type="range"
                    min={1}
                    max={NUM_MOVES}
                    value={to_move}
                    onChange={(ev) => {
                        const new_to_move = parseInt(ev.target.value);
                        setToMove(new_to_move);
                        setFromMove(
{'fraction_non_alphanumeric': 0.11587954797831342, 'fraction_numerical': 0.003984584231497812, 'mean_word_length': 1.1284582232726261, 'pattern_counts': {'":': 0, '<': 133, '<?xml version=': 0, '>': 143, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6323219', 'n_tokens_mistral': 4005, 'n_tokens_neox': 3797, 'n_words': 810}