ArduinoとPCであらゆるSwitchソフトの操作を自動化できるようにしてみた

#概要
先日、[こちら](https://qiita.com/sobassy/items/cb707e50f2f27a851886)や[こちら](https://qiita.com/chibi314/items/975784f6e951341fc6ce)でNintendo Switchの「ポケットモンスター ソード/シールド」(以下、ポケモン剣盾)の操作を自動化する方法が公開されました。

これらはいずれも、ArduinoをSwitchにコントローラとして認識させる方法を取っています。ですので理屈上はあらゆるSwitch用ゲームの自動化が可能ですが、公開されている方法はいずれもポケモン剣盾の自動化に特化した内容です。

そこでユーザーが任意のマクロを構築することで、あらゆるSwitch用ゲームの操作を手軽に自動化できる、汎用型のPCソフトを作成してみました。

##使用例

(v0.0.3～)JSONの可読性を向上させるため、入出力形式を変更しました。(2020/02/05)

###ポケットモンスター ソード・シールド

####ブティックで大人買い

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">ポケモン剣盾。洋服の数がめちゃくちゃ多くて全部買うのがめんどくさいので、自動化してみました。 <a href="https://t.co/pLTjb7ffjd">pic.twitter.com/pLTjb7ffjd</a></p>&mdash; ミチオ/MCO (@twostarsmco) <a href="https://twitter.com/twostarsmco/status/1220710025280147463?ref_src=twsrc%5Etfw">2020年1月24日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<details><summary>使用したマクロ</summary><div>


```jsonnet:BuyAll.json
{
  "Commands": [
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 1000
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 1000
    },
    {
      "CommandType": "Button",
      "ButtonID": "B",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "B",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 500
    },
    {
      "CommandType": "Button",
      "ButtonID": "DOWN",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "DOWN",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 300
    }
  ],
  "Title": "",
  "Description": ""
}
```
</div></details>

####トーナメント周回(オシャボ・かえんだま自動収集)

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">トナメ周回自動化も成功しました。動画は周回の切り替わりの瞬間です。 こちらの記事を参考にしました。 <a href="https://t.co/2nauDbO2h0">https://t.co/2nauDbO2h0</a> <a href="https://t.co/58nS12gqZW">https://t.co/58nS12gqZW</a></p>&mdash; ミチオ/MCO (@twostarsmco) <a href="https://twitter.com/twostarsmco/status/1221800146125508609?ref_src=twsrc%5Etfw">2020年1月27日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<details><summary>使用したマクロ</summary><div>

```jsonnet:TournamentAuto.json
{
  "Commands": [
    {
      "CommandType": "Stick",
      "StickID": "LSTICK",
      "X": 160,
      "Y": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    },
    {
      "CommandType": "Button",
      "ButtonID": "B",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "B",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 900
    }
  ],
  "Title": "",
  "Description": ""
}
```
</div></details>

####バドレックス&馬厳選

※要マスターボール、手持ち空き2枠、バドレックスの前でセーブ
ソフトリセット後にバドレックスと馬をマスターボールで捕獲し、馬を分離してステータスをボックスで表示する所まで実行します。
<details><summary>使用したマクロ</summary><div>

```jsonnet:Calyrex.json
{
  "Commands": [
    {
      "CommandType": "Button",
      "ButtonID": "HOME",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "HOME",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 1000
    },
    {
      "CommandType": "Button",
      "ButtonID": "X",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "X",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 1500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 2500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 2500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 18000
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 6000
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 6000
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 2500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 2500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 500
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 25000
    },
    {
      "CommandType": "Button",
      "ButtonID": "X",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 500
    },
    {
      "CommandType": "Button",
      "ButtonID": "X",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 500
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 26000
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 6000
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "X",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "X",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 1500
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 2500
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 6000
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "B",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "B",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 1500
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 1500
    },
    {
      "CommandType": "Button",
      "ButtonID": "R",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "R",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 2500
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    }
  ],
  "Title": "",
  "Description": ""
}
```
</div></details>

###コナミコマンド

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">上上下下左右左右BA！例のコマンドも自動化できました！<br><br>操作性は改良の余地アリですね…。 <a href="https://t.co/k9p4etCfru">pic.twitter.com/k9p4etCfru</a></p>&mdash; ミチオ/MCO (@twostarsmco) <a href="https://twitter.com/twostarsmco/status/1220714002399014912?ref_src=twsrc%5Etfw">2020年1月24日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<details><summary>使用したマクロ</summary><div>

```jsonnet:KONAMICommand.json
{
  "Commands": [
    {
      "CommandType": "Button",
      "ButtonID": "PLUS",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "PLUS",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "DOWN",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "DOWN",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "DOWN",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "DOWN",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "B",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "B",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "PLUS",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "PLUS",
      "TargetState": 1
    }
  ],
  "Title": "",
  "Description": ""
}
```
</div></details>

###遊☆戯☆王デュエルモンスターズ レガシー・オブ・ザ・デュエリスト：リンク・エボリューション (LotD) 

####DP自動稼ぎ

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">プランAでDP稼ぎの全自動化成功です。対戦ありがとうございました <a href="https://twitter.com/hashtag/%E9%81%8A%E6%88%AF%E7%8E%8BLotD?src=hash&amp;ref_src=twsrc%5Etfw">#遊戯王LotD</a> <a href="https://t.co/sgbl1iULZO">pic.twitter.com/sgbl1iULZO</a></p>&mdash; ミチオ/MCO (@twostarsmco) <a href="https://twitter.com/twostarsmco/status/1247930570979467266?ref_src=twsrc%5Etfw">2020年4月8日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<details><summary>使用したマクロ</summary><div>

```jsonnet:LotDDPAuto.json
{
  "Commands": [
    {
      "CommandType": "Button",
      "ButtonID": "R",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "R",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "UP",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "RIGHT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 100
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 800
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "LEFT",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 2000
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 200
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 0
    },
    {
      "CommandType": "Wait",
      "WaitTime": 50
    },
    {
      "CommandType": "Button",
      "ButtonID": "A",
      "TargetState": 1
    },
    {
      "CommandType": "Wait",
      "WaitTime": 40000
    }
  ],
  "Title": "",
  "Description": ""
}
```
</div></details>


##リポジトリ
https://github.com/twostarsmco/NSAutomation

##開発の動機
・GitHubを本格的に使ってみたい
・C#、.NETの新しめの機能や構文を、周りに気兼ねせず試してみたい
・自動テスト、DIパターンなどのプラクティスを試してみたい

##使ったもの
<dl>
  <dt>Nintendo Switch</dt>
  <dt>Windowsパソコン</dt>
  <dt>Arduino Leonardoまたは互換ボード</dt>
  <dd>筆者が使用したものは<a href="https://amzn.to/2RMS5qQ">こちら</a>です。</dd>
  <dt>FT232モジュール</dt>
  <dd>筆者が使用したものは<a href="http://akizukidenshi.com/catalog/g/gK-01977/">こちら</a>です。電源と信号電圧はArduino側から取っています。</dd>
  <dt>USBケーブルx2</dt>
  <dd>FT232とパソコンを繋ぐもの、ArduinoとSwitchを繋ぐものがそれぞれ必要です。</dd>
</dl>

#使用方法
1. [こちら](https://github.com/twostarsmco/NSAutomation/releases)からNSAutomationWin.zipをダウンロードする
1. [こちらの記事](https://qiita.com/chibi314/items/975784f6e951341fc6ce)の方法で、Switch⇔Arduino Leonardo⇔FT232⇔PCを接続する
1. ArduinoがSwitchのコントローラとして認識された状態で、NSAutomationWin.exeを起動する
1. FT232が接続されたCOMポートを、ドロップダウンメニューで選択する
1. 画面の表にマクロを記述し、Runボタンを押す
1. マクロが実行される
1. マクロをファイルに保存して、後で読み込んだり、他のユーザーと共有したりする

##マクロでできること
- ボタンの操作
ボタンと、左右スティックの押し込みを押す(PRESS)/離す(RELEASE)操作ができます。明示的に離すまで、押し込んだ状態が続きます。

- スティックの操作
左右のスティックを、縦横それぞれ256段階へ傾けることができます。一度傾けるとその状態をキープするので、終わったらニュートラルポジションの(128, 128)へ明示的に戻す必要があります。

- 待機する
次の行のコマンドの実行を、指定したミリ秒だけ遅らせます。あまりに速くコマンドを実行させるとSwitchが反応できないので、適当に遅らせてあげてください[^1]。
内部的には、暫定的にTask.Delayを使った実装としています。WindowsではMultimediaTimerを使うと最高の時間精度を実現できると聞いた事があるので、将来的にはこちらに切り替えたいですね。めざせ[TASbot](https://qiita.com/naari3/items/9565f05e66d0eaa8c280)。


#学んだこと
##工夫したところ
###マクロを編集、保存、読み込みできるようにした
汎用性を求める上で、これらの機能は必須。

###マクロのループ実行と中断をできるようにした
「一連のボタン操作を繰り返し入力する」使用方法が多いと想定しています。

###ソフトの内部構造を徹底的に疎結合にした
ソフトの構成を

- 制御コマンドの共通データモデル、、共通インタフェース
- コマンドを解釈して実行するバックエンド
- ユーザインタフェース

の3つのプロジェクトに分けました。将来的に、例えば特定のゲームソフトに特化した自動化ソフトを作るだとか、Windows以外のOSで同様のソフトを作る時などに流用が効くはずです(いつになるやら分かりませんが)。
スマホから、PCと同じマクロファイルを読んでSwitchを制御できたら楽しそうですね。あるいはSwitchの動画キャプチャと画像認識、強化学習を絡めて、任意のSwitchタイトルを自動強化学習……なんて事が出来ると面白いと思いませんか？

また開発中は、バックエンドをモックに差し替えることでUIのデバッグを通信処理と切り離して行うことができます。多少オーバーエンジニアリング気味かもしれませんが、デバッグはかなり楽でした。PC外部との通信を行うソフトなら、小さなモノでもこのように疎結合にするメリットはあると感じました。

##苦労したところ
###共通の親を継承した複数の子クラスをJSONへSerialize、Deserializeする処理
3種類のコマンドをそれぞれ、共通の親クラスを持つ別のクラスとして定義しています。各コマンドのパラメータを静的に型付けされた形で利用したかったためです。……が、マクロはこれらのコマンドのインスタンスを「共通の親クラスの配列」として保持しているので、マクロをデフォルトの設定でJSONにSerializeすると、どの子クラスのインスタンスだったのかという情報が失われてしまい、Deserializeが不可能になります。

今回はJSON.NETの設定に型情報を出力するものがあったので、それを利用~~しました~~していたのですが、JSONの可読性が著しく損なわれてしまいます。結局、型情報をコンパクトにJSON内に記述することにしました。

<div><details><summary>`変更前。`</summary>

```c#:Macro.cs
public string ToJSON(JsonSerializerSettings settings = null)
{
    settings = settings ?? new JsonSerializerSettings() {
             Formatting = Formatting.Indented };

    settings.TypeNameHandling = TypeNameHandling.Auto;
    return JsonConvert.SerializeObject(this, settings);
}

public static Macro FromJSON(string json)
{
    return JsonConvert.DeserializeObject<Macro>(
        json, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto });
}
```
ただこれをそのまま使うと、こんな感じで"$type"が入ってJSONの可読性が若干犠牲になるのが悩ましい所。

```jsonnet:PressA.json
{
  "Commands": {
    "$type": "Command.ICommand[], Common",
    "$values": [
      {
        "$type": "Command.OperateButton, Common",
        "TargetState": 0,
        "TargetControlID": 4
      },
      {
        "$type": "Command.Wait, Common",
        "WaitTime": 50
      },
      {
        "$type": "Command.OperateButton, Common",
        "TargetState": 1,
        "TargetControlID": 4
      },
      {
        "$type": "Command.Wait, Common",
        "WaitTime": 950
      }
    ]
  },
  "Description": null
}
```
こういうユースケースではどうするのがいいんでしょうかね。

</div></details>

これに関しては新しい知見を得ることができたので、別途記事に~~したいと思います~~しました:

[Json.NETで、継承関係のあるクラスを可読性を重視しながらシリアライズ/デシリアライズする方法](https://qiita.com/twostarsmco/items/af91a69068472066a181)

#今後の課題
- 例外処理にたぶん穴が残ってるので塞ぐ
- 多言語対応
- PC側のUIから、スティックを256段階で操作できるようにする
- PCのキーボードでボタンを操作できるようにする
- 60FPS単位の、正確なタイミングでの自動操作を可能にする

#注意
このPCソフトですが、Switchのコントローラで可能な操作は大半が実行可能です。悪意あるマクロや、動作確認が不十分なマクロを不用意に実行すると

- ゲーム内の貴重なアイテムを消費させられる
- セーブデータを消去される
- オンラインショップでアイテムを購入させられる

ような事もあり得ます。
また電子工作のミスが、最悪の場合Switchの物理的故障に繋がる可能性もあります。十分にご注意ください。これらのハード・ソフトに発生した不具合については責任を負いかねますので、了承の上でご利用下さい。

[^1]: ソフトにもよります。ポケモン剣盾の場合は100ms程度必要です。ファミコンのグラディウスでは50msでも安定しました。