雀魂の牌譜画面をキーボードで操作する

:::note warn
**スクリプトの利用は、自己責任でお願いします。**
:::

雀魂の牌譜画面を、キーボードで操作できるようにするスクリプトです。開発者ツールで実行できます。

<dl>
<dt>preRound (↑) / nextRound (↓)</dt>
<dd>前局 / 次局に移ります。<br><br></dd>
<dt>preXun (←) / nextXun (→)</dt>
<dd>前巡 / 次巡に移ります。<br><br></dd>
<dt>preStep (Z) / nextStep (他の任意のキー)</dt>
<dd>1つ前 / 1つ後のプレイヤーの操作に移ります。<br><br></dd>
<dt>paifuya (P)</dt>
<dd>プレイヤーの牌譜屋のページを開きます。<br><br></dd>
<dt>playerInfo (I)</dt>
<dd>プレイヤーのプロフィールを開きます。<br><br></dd>
<dt>gameEnd (E)</dt>
<dd>最終局の結果画面で押すと、対局結果画面に移ります。（他のキーを押した場合は、東一局に移ります。）<br><br></dd>
<dt>toggleTehai (T) / toggleHoju (H) / toggleAnim (A) / toggleName (N)</dt>
<dd>牌譜画面の表示を切り替えます。</dd>
</dl>

<details>
<summary>その他の機能はこちら</summary>
<dl>
<dt>delta (D) / yama (Y) / rounds (R)</dt>
<dd>点差、牌山、局ごとの点数移動を表示します。<br><br></dd>
<dt>quit (Q / Esc)</dt>
<dd>牌譜画面から退出します。<br><br></dd>
<dt>favorite (F)</dt>
<dd>牌譜をブックマークに登録します。<br><br></dd>
<dt>play (S)</dt>
<dd>牌譜を再生します。<br><br></dd>
<dt>kamicha 
(PageUp)
 / shimocha 
(PageDown)
</dt>
<dd>上家 / 下家のプレイヤーの視点に移ります。</dd>
</dl>
kamicha と shimocha は、三人麻雀の牌譜でバグが発生することがあるため、コメントアウトしています。
</details>
<br>


```JavaScript
window.config = {
    ArrowLeft: "preXun",
    ArrowRight: "nextXun",
    ArrowUp: "preRound",
    ArrowDown: "nextRound",
    KeyZ: "preStep",
    default: "nextStep",

    KeyP: "paifuya",
    KeyI: "playerInfo",
    KeyE: "gameEnd",
    KeyT: "toggleTehai",
    KeyH: "toggleHoju",
    KeyA: "toggleAnim",
    KeyN: "toggleName",

    KeyD: "delta",
    KeyY: "yama",
    KeyR: "rounds",
    Escape: "quit",
    KeyQ: "quit",
    KeyF: "favorite",
    KeyS: "play",
    // PageUp: "kamicha",
    // PageDown: "shimocha",
};

window.majsoul_keydown = event => {
    const MJ = window.game?.Scene_MJ?.Inst;
    if (!MJ?.active) {
        return;
    }
    const DMgr = view.DesktopMgr.Inst;
    const Replay = uiscript.UI_Replay.Inst;
    const action = config[event.code] || config.default;
    if (
        !action
        || DMgr.mode !== view.EMJMode.paipu
        || Replay.pop_collectinput.me.visible
        || event.ctrlKey
        || event.altKey
        || event.metaKey
    ) {
        return;
    }
    const id = DMgr.player_datas[DMgr.localPosition2Seat(0)].account_id;
    const DInfo = uiscript.UI_DesktopInfo.Inst;
    const GameEnd = uiscript.UI_GameEnd.Inst;
    const RoundEnd = [
        uiscript.UI_Win.Inst,
        uiscript.UI_ScoreChange.Inst,
        uiscript.UIMgr.Inst._ui_liuju,
    ].find(ui => ui.enable);

    if (action === "quit") {
        MJ.ForceOut();
    }
    else if (GameEnd.enable) {
        if (!GameEnd.btn_back.visible) {
            return;
        }
        GameEnd.enable = false;
        Laya.loader.clearTextureRes(GameEnd.illust.skin);
        Replay.onBack();
    }
    else if (RoundEnd) {
        if (action !== "gameEnd" && Replay.round_index + 1 >= Replay.rounds.length) {
            Replay.round_index = -1;
            Replay.action_index = 0;
        }
        if (RoundEnd.btn_confirm.disabled || !RoundEnd.btn_confirm.visible) {
            return;
        }
        (RoundEnd.onConfirm || RoundEnd.onBtnConfirm).call(RoundEnd);
    }
    else if (Replay.auto_play) {
        Replay.auto_play = false;
    }
    else if (action === "play") {
        Replay.auto_play = true;
    }
    else if (action === "favorite") {
        DInfo._btn_collect.clickHandler.method();
    }
    else if (action === "paifuya") {
        const rule = DMgr.game_config.mode.mode < 10 ? "ako" : "ikeda";
        const room = DMgr.game_config.meta.mode_id || "";
        if (id) {
            window.open(`https://${rule}.sapk.ch/player/${id}/${room}`, "_blank");
        }
    }
    else if (action === "playerInfo") {
        const PlayerInfo = uiscript.UI_OtherPlayerInfo.Inst;
        if (PlayerInfo.enable) {
            return PlayerInfo.close();
        }
        if (id && DMgr.gameing) {
            PlayerInfo.show(
                id,
                DMgr.game_config.mode.mode < 10 ? 1 : 2,
                DMgr.game_config.category === 1 ? 1 : 2,
                DMgr.game_config.meta.mode_id === game.EMatchMode.shilian ? 4: 1
            );
        }
    }
    else if (["kamicha", "shimocha"].includes(action)) {
        const pos = DMgr.localPosition2Seat(action === "kamicha" ? 3 : 1);
        DMgr.changeMainbody(pos >= 0 ? pos : DMgr.localPosition2Seat(2));
    }
    else if (action.startsWith("toggle")) {
        const btns = {
            toggleTehai: "btn_shoupai",
            toggleHoju: "btn_paopai",
            toggleAnim: "btn_anim",
            toggleName: "btn_hidename",
        };
        Replay.me.getChildByName("config").getChildByName(btns[action]).clickHandler.method();
    }
    else if (action === "delta") {
        DInfo.showscoredeltaing = !DInfo.showscoredeltaing;
        DMgr.setScoreDelta(DInfo.showscoredeltaing);
    }
    else if (action === "rounds") {
        const Rounds = Replay.page_chang;
        Rounds[Rounds.enable ? "close" : "show"](Replay.rounds);
    }
    else if (action === "yama") {
        const Yama = Replay.page_paishan;
        Yama[Yama.me.visible ? "close": "show"]();
    }
    else {
        (Replay[action] || Replay[config.default]).call(Replay);
    }
};

window.addEventListener("keydown", majsoul_keydown, true);
```