nodeでテンプレートエンジンっぽいものを作った

## 背景
同じようなページを複製したいけど、それだけのためにEJSやPugを入れるのも面倒。。。
じゃあ自分でサクッと作ろう！

## 環境
node 20.10.0
npm 10.2.3

## 前提
以下のポケモン151匹のデータが入ったJSONをもとに、 (JSONは記事最下部に記載)
```pokeData.json
[
  {
    "no": 1,
    "name": "フシギダネ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 45,
      "attack": 49,
      "defense": 49,
      "spAttack": 65,
      "spDefense": 65,
      "speed": 45
    }
  },
  {
    "no": 2,
    "name": "フシギソウ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 60,
      "attack": 62,
      "defense": 63,
      "spAttack": 80,
      "spDefense": 80,
      "speed": 60
    }
  },
  {
    "no": 3,
    "name": "フシギバナ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 80,
      "attack": 82,
      "defense": 83,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 80
    }
  },
  ......
  {
    "no": 151,
    "name": "ミュウ",
    "abilities": ["シンクロ"],
    "stats": {
      "hp": 100,
      "attack": 100,
      "defense": 100,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 100
    }
  }
]
```

以下のようなファイルを量産します。
（タイトル、h1、ulの中身、dlの中身が変化）
```1.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>フシギダネ</title>
</head>
<body>
  <h1>フシギダネ</h1>
  <ul>
    <li>しんりょく</li>
  </ul>
  <dl>
    <dt>HP</dt>
    <dd>45</dd>
    <dt>こうげき</dt>
    <dd>49</dd>
    <dt>ぼうぎょ</dt>
    <dd>49</dd>
    <dt>とくこう</dt>
    <dd>65</dd>
    <dt>とくぼう</dt>
    <dd>65</dd>
    <dt>すばやさ</dt>
    <dd>45</dd>
  </dl>
</body>
</html>
```

## 実装
### まずは１ページ作成してみる
プロジェクトルートにmain.jsとbuildディレクトリを作成して、main.jsに以下を記述します
（都合上、ulは後ほど追記します）
```main.js
const fs = require('fs');

// pokeData.jsonを読み込む
const pokeData = require('./pokeData.json');

// pokeDataの配列の要素を引数に取り、htmlを生成する
const generatePage = ({no, name, stats}) => {
  const html = `
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>フシギダネ</title>
</head>
<body>
  <h1>フシギダネ</h1>
  <dl>
    <dt>HP</dt>
    <dd>45</dd>
    <dt>こうげき</dt>
    <dd>49</dd>
    <dt>ぼうぎょ</dt>
    <dd>49</dd>
    <dt>とくこう</dt>
    <dd>65</dd>
    <dt>とくぼう</dt>
    <dd>65</dd>
    <dt>すばやさ</dt>
    <dd>45</dd>
  </dl>
</body>
</html>
`

  fs.writeFileSync(`./build/${no}.html`,html);
}

// pokeDataの1番初め（フシギダネ）のページを作成
generatePage(pokeData[0])
```

fs.writeFileSyncを用い、第1引数に書き出すファイルパス、第2引数に書き込むデータを指定することでファイルを作成することができます。


コードを実行します。
```
node main.js
```

buildディレクトリに1.htmlが生成されているはずです。

### 151ページ作成してみる
変数を使用して各項目がページごとに変わるようにします。
また、pokeDataをforEachで回して、151ページ分生成します。

```diff_javascript:main.js
  const fs = require('fs');

  const pokeData = require('./pokeData.json');


  const generatePage = ({no, name, stats}) => {
    const html = `
  <!DOCTYPE html>
  <html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-   <title>フシギダネ</title>
+   <title>${name}</title>
  </head>
  <body>
-   <h1>フシギダネ</h1>
+   <h1>${name}</h1>
    <dl>
      <dt>HP</dt>
-     <dd>45</dd>
+     <dd>${stats.hp}</dd>
      <dt>こうげき</dt>
-     <dd>49</dd>
+     <dd>${stats.attack}</dd>
      <dt>ぼうぎょ</dt>
-     <dd>49</dd>
+     <dd>${stats.defense}</dd>
      <dt>とくこう</dt>
-     <dd>65</dd>
+     <dd>${stats.spAttack}</dd>
      <dt>とくぼう</dt>
-     <dd>65</dd>
+     <dd>${stats.spDefense}</dd>
      <dt>すばやさ</dt>
-     <dd>45</dd>
+     <dd>${stats.speed}</dd>
    </dl>
  </body>
  </html>
  `

    fs.writeFileSync(`./build/${no}.html`,html)
  }
  
- generatePage(pokeData[0])
+ pokeData.forEach(generatePage)

  // 追記：上記forEachは下記とおなじ。
  // pokeData.forEach(pokemon => {
  //  generatePage(pokemon);
  // })
```

コードを実行すると151ページ分生成されているかと思います。

### ループを組み込んでみる
指定の箇所を変えるだけであれば上記で済むのですが、途中にループ処理が入るとやや面倒になります。
今回はポケモンの特性（abilities）の数だけループを回してliタグを生成するようにします。

```diff_javascript:main.js
  const fs = require('fs');

  const pokeData = require('./pokeData.json');


- const generatePage = ({no, name, stats}) => {
+ const generatePage = ({no, name, abilities, stats}) => {
+
+   const abilitiesList = () => {
+     let list = '';
+
+     for(const ability of abilities) {
+       list += `
+     <li>${ability}</li>
+ `;
+     }
+     return list;
+   }



    const html = `
  <!DOCTYPE html>
  <html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>${name}</title>
  </head>
  <body>
    <h1>${name}</h1>
+   <ul>
+ ${abilitiesList()}
+   </ul>
    <dl>
      <dt>HP</dt>
      <dd>${stats.hp}</dd>
      <dt>こうげき</dt>
      <dd>${stats.attack}</dd>
      <dt>ぼうぎょ</dt>
      <dd>${stats.defense}</dd>
      <dt>とくこう</dt>
      <dd>${stats.spAttack}</dd>
      <dt>とくぼう</dt>
      <dd>${stats.spDefense}</dd>
      <dt>すばやさ</dt>
      <dd>${stats.speed}</dd>
    </dl>
  </body>
  </html>
  `
    


    fs.writeFileSync(`./build/${no}.html`,html)
  }

  pokeData.forEach(generatePage)

```

まず、ループする箇所を関数として切り出します（ abilitiesList関数 ）
関数内部でループを回し、htmlを出力させます。今回はabilitiesの要素の数だけループを回し、その分のliタグを出力しています。


コードを実行すると151ページ分が更新され、特性の分だけliタグが出力されています。

## 結果
簡単なものであれば自力でページを複製することができました。
ただし、ループの処理がややこしくなるため、ループ箇所が多い場合はかなりしんどくなりそうです。
いずれにせよ「量産できればそれでOK」といった場合でなければやはりテンプレートエンジンをつかうべきですね...。


## 今回使用したJSONデータ
```pokeData.json

[
  {
    "no": 1,
    "name": "フシギダネ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 45,
      "attack": 49,
      "defense": 49,
      "spAttack": 65,
      "spDefense": 65,
      "speed": 45
    }
  },
  {
    "no": 2,
    "name": "フシギソウ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 60,
      "attack": 62,
      "defense": 63,
      "spAttack": 80,
      "spDefense": 80,
      "speed": 60
    }
  },
  {
    "no": 3,
    "name": "フシギバナ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 80,
      "attack": 82,
      "defense": 83,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 80
    }
  },
  {
    "no": 4,
    "name": "ヒトカゲ",
    "abilities": ["もうか"],
    "stats": {
      "hp": 39,
      "attack": 52,
      "defense": 43,
      "spAttack": 60,
      "spDefense": 50,
      "speed": 65
    }
  },
  {
    "no": 5,
    "name": "リザード",
    "abilities": ["もうか"],
    "stats": {
      "hp": 58,
      "attack": 64,
      "defense": 58,
      "spAttack": 80,
      "spDefense": 65,
      "speed": 80
    }
  },
  {
    "no": 6,
    "name": "リザードン",
    "abilities": ["もうか"],
    "stats": {
      "hp": 78,
      "attack": 84,
      "defense": 78,
      "spAttack": 109,
      "spDefense": 85,
      "speed": 100
    }
  },
  {
    "no": 7,
    "name": "ゼニガメ",
    "abilities": ["げきりゅう"],
    "stats": {
      "hp": 44,
      "attack": 48,
      "defense": 65,
      "spAttack": 50,
      "spDefense": 64,
      "speed": 43
    }
  },
  {
    "no": 8,
    "name": "カメール",
    "abilities": ["げきりゅう"],
    "stats": {
      "hp": 59,
      "attack": 63,
      "defense": 80,
      "spAttack": 65,
      "spDefense": 80,
      "speed": 58
    }
  },
  {
    "no": 9,
    "name": "カメックス",
    "abilities": ["げきりゅう"],
    "stats": {
      "hp": 79,
      "attack": 83,
      "defense": 100,
      "spAttack": 85,
      "spDefense": 105,
      "speed": 78
    }
  },
  {
    "no": 10,
    "name": "キャタピー",
    "abilities": ["りんぷん"],
    "stats": {
      "hp": 45,
      "attack": 30,
      "defense": 35,
      "spAttack": 20,
      "spDefense": 20,
      "speed": 45
    }
  },
  {
    "no": 11,
    "name": "トランセル",
    "abilities": ["だっぴ"],
    "stats": {
      "hp": 50,
      "attack": 20,
      "defense": 55,
      "spAttack": 25,
      "spDefense": 25,
      "speed": 30
    }
  },
  {
    "no": 12,
    "name": "バタフリー",
    "abilities": ["ふくがん"],
    "stats": {
      "hp": 60,
      "attack": 45,
      "defense": 50,
      "spAttack": 90,
      "spDefense": 80,
      "speed": 70
    }
  },
  {
    "no": 13,
    "name": "ビードル",
    "abilities": ["りんぷん"],
    "stats": {
      "hp": 40,
      "attack": 35,
      "defense": 30,
      "spAttack": 20,
      "spDefense": 20,
      "speed": 50
    }
  },
  {
    "no": 14,
    "name": "コクーン",
    "abilities": ["だっぴ"],
    "stats": {
      "hp": 45,
      "attack": 25,
      "defense": 50,
      "spAttack": 25,
      "spDefense": 25,
      "speed": 35
    }
  },
  {
    "no": 15,
    "name": "スピアー",
    "abilities": ["むしのしらせ"],
    "stats": {
      "hp": 65,
      "attack": 90,
      "defense": 40,
      "spAttack": 45,
      "spDefense": 80,
      "speed": 75
    }
  },
  {
    "no": 16,
    "name": "ポッポ",
    "abilities": ["するどいめ", "ちどりあし"],
    "stats": {
      "hp": 40,
      "attack": 45,
      "defense": 40,
      "spAttack": 35,
      "spDefense": 35,
      "speed": 56
    }
  },
  {
    "no": 17,
    "name": "ピジョン",
    "abilities": ["するどいめ", "ちどりあし"],
    "stats": {
      "hp": 63,
      "attack": 60,
      "defense": 55,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 71
    }
  },
  {
    "no": 18,
    "name": "ピジョット",
    "abilities": ["するどいめ", "ちどりあし"],
    "stats": {
      "hp": 83,
      "attack": 80,
      "defense": 75,
      "spAttack": 70,
      "spDefense": 70,
      "speed": 101
    }
  },
  {
    "no": 19,
    "name": "コラッタ",
    "abilities": ["にげあし", "こんじょう"],
    "stats": {
      "hp": 30,
      "attack": 56,
      "defense": 35,
      "spAttack": 25,
      "spDefense": 35,
      "speed": 72
    }
  },
  {
    "no": 20,
    "name": "ラッタ",
    "abilities": ["にげあし", "こんじょう"],
    "stats": {
      "hp": 55,
      "attack": 81,
      "defense": 60,
      "spAttack": 50,
      "spDefense": 70,
      "speed": 97
    }
  },
  {
    "no": 21,
    "name": "オニスズメ",
    "abilities": ["するどいめ"],
    "stats": {
      "hp": 40,
      "attack": 60,
      "defense": 30,
      "spAttack": 31,
      "spDefense": 31,
      "speed": 70
    }
  },
  {
    "no": 22,
    "name": "オニドリル",
    "abilities": ["するどいめ"],
    "stats": {
      "hp": 65,
      "attack": 90,
      "defense": 65,
      "spAttack": 61,
      "spDefense": 61,
      "speed": 100
    }
  },
  {
    "no": 23,
    "name": "アーボ",
    "abilities": ["いかく", "だっぴ"],
    "stats": {
      "hp": 35,
      "attack": 60,
      "defense": 44,
      "spAttack": 40,
      "spDefense": 54,
      "speed": 55
    }
  },
  {
    "no": 24,
    "name": "アーボック",
    "abilities": ["いかく", "だっぴ"],
    "stats": {
      "hp": 60,
      "attack": 95,
      "defense": 69,
      "spAttack": 65,
      "spDefense": 79,
      "speed": 80
    }
  },
  {
    "no": 25,
    "name": "ピカチュウ",
    "abilities": ["せいでんき"],
    "stats": {
      "hp": 35,
      "attack": 55,
      "defense": 40,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 90
    }
  },
  {
    "no": 26,
    "name": "ライチュウ",
    "abilities": ["せいでんき"],
    "stats": {
      "hp": 60,
      "attack": 90,
      "defense": 55,
      "spAttack": 90,
      "spDefense": 80,
      "speed": 110
    }
  },
  {
    "no": 27,
    "name": "サンド",
    "abilities": ["すながくれ"],
    "stats": {
      "hp": 50,
      "attack": 75,
      "defense": 85,
      "spAttack": 20,
      "spDefense": 30,
      "speed": 40
    }
  },
  {
    "no": 28,
    "name": "サンドパン",
    "abilities": ["すながくれ"],
    "stats": {
      "hp": 75,
      "attack": 100,
      "defense": 110,
      "spAttack": 45,
      "spDefense": 55,
      "speed": 65
    }
  },
  {
    "no": 29,
    "name": "ニドラン♀",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 55,
      "attack": 47,
      "defense": 52,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 41
    }
  },
  {
    "no": 30,
    "name": "ニドリーナ",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 70,
      "attack": 62,
      "defense": 67,
      "spAttack": 55,
      "spDefense": 55,
      "speed": 56
    }
  },
  {
    "no": 31,
    "name": "ニドクイン",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 90,
      "attack": 92,
      "defense": 87,
      "spAttack": 75,
      "spDefense": 85,
      "speed": 76
    }
  },
  {
    "no": 32,
    "name": "ニドラン♂",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 46,
      "attack": 57,
      "defense": 40,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 50
    }
  },
  {
    "no": 33,
    "name": "ニドリーノ",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 61,
      "attack": 72,
      "defense": 57,
      "spAttack": 55,
      "spDefense": 55,
      "speed": 65
    }
  },
  {
    "no": 34,
    "name": "ニドキング",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 81,
      "attack": 102,
      "defense": 77,
      "spAttack": 85,
      "spDefense": 75,
      "speed": 85
    }
  },
  {
    "no": 35,
    "name": "ピッピ",
    "abilities": ["メロメロボディ", "マジックガード"],
    "stats": {
      "hp": 70,
      "attack": 45,
      "defense": 48,
      "spAttack": 60,
      "spDefense": 65,
      "speed": 35
    }
  },
  {
    "no": 36,
    "name": "ピクシー",
    "abilities": ["メロメロボディ", "マジックガード"],
    "stats": {
      "hp": 95,
      "attack": 70,
      "defense": 73,
      "spAttack": 95,
      "spDefense": 90,
      "speed": 60
    }
  },
  {
    "no": 37,
    "name": "ロコン",
    "abilities": ["もらいび"],
    "stats": {
      "hp": 38,
      "attack": 41,
      "defense": 40,
      "spAttack": 50,
      "spDefense": 65,
      "speed": 65
    }
  },
  {
    "no": 38,
    "name": "キュウコン",
    "abilities": ["もらいび"],
    "stats": {
      "hp": 73,
      "attack": 76,
      "defense": 75,
      "spAttack": 81,
      "spDefense": 100,
      "speed": 100
    }
  },
  {
    "no": 39,
    "name": "プリン",
    "abilities": ["メロメロボディ", "かちき"],
    "stats": {
      "hp": 115,
      "attack": 45,
      "defense": 20,
      "spAttack": 45,
      "spDefense": 25,
      "speed": 20
    }
  },
  {
    "no": 40,
    "name": "プクリン",
    "abilities": ["メロメロボディ", "かちき"],
    "stats": {
      "hp": 140,
      "attack": 70,
      "defense": 45,
      "spAttack": 85,
      "spDefense": 50,
      "speed": 45
    }
  },
  {
    "no": 41,
    "name": "ズバット",
    "abilities": ["せいしんりょく"],
    "stats": {
      "hp": 40,
      "attack": 45,
      "defense": 35,
      "spAttack": 30,
      "spDefense": 40,
      "speed": 55
    }
  },
  {
    "no": 42,
    "name": "ゴルバット",
    "abilities": ["せいしんりょく"],
    "stats": {
      "hp": 75,
      "attack": 80,
      "defense": 70,
      "spAttack": 65,
      "spDefense": 75,
      "speed": 90
    }
  },
  {
    "no": 43,
    "name": "ナゾノクサ",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 45,
      "attack": 50,
      "defense": 55,
      "spAttack": 75,
      "spDefense": 65,
      "speed": 30
    }
  },
  {
    "no": 44,
    "name": "クサイハナ",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 60,
      "attack": 65,
      "defense": 70,
      "spAttack": 85,
      "spDefense": 75,
      "speed": 40
    }
  },
  {
    "no": 45,
    "name": "ラフレシア",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 75,
      "attack": 80,
      "defense": 85,
      "spAttack": 110,
      "spDefense": 90,
      "speed": 50
    }
  },
  {
    "no": 46,
    "name": "パラス",
    "abilities": ["ほうし", "かんそうはだ"],
    "stats": {
      "hp": 35,
      "attack": 70,
      "defense": 55,
      "spAttack": 45,
      "spDefense": 55,
      "speed": 25
    }
  },
  {
    "no": 47,
    "name": "パラセクト",
    "abilities": ["ほうし", "かんそうはだ"],
    "stats": {
      "hp": 60,
      "attack": 95,
      "defense": 80,
      "spAttack": 60,
      "spDefense": 80,
      "speed": 30
    }
  },
  {
    "no": 48,
    "name": "コンパン",
    "abilities": ["ふくがん", "いろめがね"],
    "stats": {
      "hp": 60,
      "attack": 55,
      "defense": 50,
      "spAttack": 40,
      "spDefense": 55,
      "speed": 45
    }
  },
  {
    "no": 49,
    "name": "モルフォン",
    "abilities": ["りんぷん", "いろめがね"],
    "stats": {
      "hp": 70,
      "attack": 65,
      "defense": 60,
      "spAttack": 90,
      "spDefense": 75,
      "speed": 90
    }
  },
  {
    "no": 50,
    "name": "ディグダ",
    "abilities": ["すながくれ", "ありじごく"],
    "stats": {
      "hp": 10,
      "attack": 55,
      "defense": 25,
      "spAttack": 35,
      "spDefense": 45,
      "speed": 95
    }
  },
  {
    "no": 51,
    "name": "ダグトリオ",
    "abilities": ["すながくれ", "ありじごく"],
    "stats": {
      "hp": 35,
      "attack": 100,
      "defense": 50,
      "spAttack": 50,
      "spDefense": 70,
      "speed": 120
    }
  },
  {
    "no": 52,
    "name": "ニャース",
    "abilities": ["ものひろい", "テクニシャン"],
    "stats": {
      "hp": 40,
      "attack": 45,
      "defense": 35,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 90
    }
  },
  {
    "no": 53,
    "name": "ペルシアン",
    "abilities": ["じゅうなん", "テクニシャン"],
    "stats": {
      "hp": 65,
      "attack": 70,
      "defense": 60,
      "spAttack": 65,
      "spDefense": 65,
      "speed": 115
    }
  },
  {
    "no": 54,
    "name": "コダック",
    "abilities": ["しめりけ", "ノーてんき"],
    "stats": {
      "hp": 50,
      "attack": 52,
      "defense": 48,
      "spAttack": 65,
      "spDefense": 50,
      "speed": 55
    }
  },
  {
    "no": 55,
    "name": "ゴルダック",
    "abilities": ["しめりけ", "ノーてんき"],
    "stats": {
      "hp": 80,
      "attack": 82,
      "defense": 78,
      "spAttack": 95,
      "spDefense": 80,
      "speed": 85
    }
  },
  {
    "no": 56,
    "name": "マンキー",
    "abilities": ["やるき", "いかりのつぼ"],
    "stats": {
      "hp": 40,
      "attack": 80,
      "defense": 35,
      "spAttack": 35,
      "spDefense": 45,
      "speed": 70
    }
  },
  {
    "no": 57,
    "name": "オコリザル",
    "abilities": ["やるき", "いかりのつぼ"],
    "stats": {
      "hp": 65,
      "attack": 105,
      "defense": 60,
      "spAttack": 60,
      "spDefense": 70,
      "speed": 95
    }
  },
  {
    "no": 58,
    "name": "ガーディ",
    "abilities": ["いかく", "もらいび"],
    "stats": {
      "hp": 55,
      "attack": 70,
      "defense": 45,
      "spAttack": 70,
      "spDefense": 50,
      "speed": 60
    }
  },
  {
    "no": 59,
    "name": "ウインディ",
    "abilities": ["いかく", "もらいび"],
    "stats": {
      "hp": 90,
      "attack": 110,
      "defense": 80,
      "spAttack": 100,
      "spDefense": 80,
      "speed": 95
    }
  },
  {
    "no": 60,
    "name": "ニョロモ",
    "abilities": ["ちょすい", "しめりけ"],
    "stats": {
      "hp": 40,
      "attack": 50,
      "defense": 40,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 90
    }
  },
  {
    "no": 61,
    "name": "ニョロゾ",
    "abilities": ["ちょすい", "しめりけ"],
    "stats": {
      "hp": 65,
      "attack": 65,
      "defense": 65,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 90
    }
  },
  {
    "no": 62,
    "name": "ニョロボン",
    "abilities": ["ちょすい", "しめりけ"],
    "stats": {
      "hp": 90,
      "attack": 95,
      "defense": 95,
      "spAttack": 70,
      "spDefense": 90,
      "speed": 70
    }
  },
  {
    "no": 63,
    "name": "ケーシィ",
    "abilities": ["シンクロ", "せいしんりょく"],
    "stats": {
      "hp": 25,
      "attack": 20,
      "defense": 15,
      "spAttack": 105,
      "spDefense": 55,
      "speed": 90
    }
  },
  {
    "no": 64,
    "name": "ユンゲラー",
    "abilities": ["シンクロ", "せいしんりょく"],
    "stats": {
      "hp": 40,
      "attack": 35,
      "defense": 30,
      "spAttack": 120,
      "spDefense": 70,
      "speed": 105
    }
  },
  {
    "no": 65,
    "name": "フーディン",
    "abilities": ["シンクロ", "せいしんりょく"],
    "stats": {
      "hp": 55,
      "attack": 50,
      "defense": 45,
      "spAttack": 135,
      "spDefense": 95,
      "speed": 120
    }
  },
  {
    "no": 66,
    "name": "ワンリキー",
    "abilities": ["こんじょう", "ノーガード"],
    "stats": {
      "hp": 70,
      "attack": 80,
      "defense": 50,
      "spAttack": 35,
      "spDefense": 35,
      "speed": 35
    }
  },
  {
    "no": 67,
    "name": "ゴーリキー",
    "abilities": ["こんじょう", "ノーガード"],
    "stats": {
      "hp": 80,
      "attack": 100,
      "defense": 70,
      "spAttack": 50,
      "spDefense": 60,
      "speed": 45
    }
  },
  {
    "no": 68,
    "name": "カイリキー",
    "abilities": ["こんじょう", "ノーガード"],
    "stats": {
      "hp": 90,
      "attack": 130,
      "defense": 80,
      "spAttack": 65,
      "spDefense": 85,
      "speed": 55
    }
  },
  {
    "no": 69,
    "name": "マダツボミ",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 50,
      "attack": 75,
      "defense": 35,
      "spAttack": 70,
      "spDefense": 30,
      "speed": 40
    }
  },
  {
    "no": 70,
    "name": "ウツドン",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 65,
      "attack": 90,
      "defense": 50,
      "spAttack": 85,
      "spDefense": 45,
      "speed": 55
    }
  },
  {
    "no": 71,
    "name": "ウツボット",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 80,
      "attack": 105,
      "defense": 65,
      "spAttack": 100,
      "spDefense": 70,
      "speed": 70
    }
  },
  {
    "no": 72,
    "name": "メノクラゲ",
    "abilities": ["クリアボディ", "ヘドロえき"],
    "stats": {
      "hp": 40,
      "attack": 40,
      "defense": 35,
      "spAttack": 50,
      "spDefense": 100,
      "speed": 70
    }
  },
  {
    "no": 73,
    "name": "ドククラゲ",
    "abilities": ["クリアボディ", "ヘドロえき"],
    "stats": {
      "hp": 80,
      "attack": 70,
      "defense": 65,
      "spAttack": 80,
      "spDefense": 120,
      "speed": 100
    }
  },
  {
    "no": 74,
    "name": "イシツブテ",
    "abilities": ["いしあたま", "がんじょう"],
    "stats": {
      "hp": 40,
      "attack": 80,
      "defense": 100,
      "spAttack": 30,
      "spDefense": 30,
      "speed": 20
    }
  },
  {
    "no": 75,
    "name": "ゴローン",
    "abilities": ["いしあたま", "がんじょう"],
    "stats": {
      "hp": 55,
      "attack": 95,
      "defense": 115,
      "spAttack": 45,
      "spDefense": 45,
      "speed": 35
    }
  },
  {
    "no": 76,
    "name": "ゴローニャ",
    "abilities": ["いしあたま", "がんじょう"],
    "stats": {
      "hp": 80,
      "attack": 120,
      "defense": 130,
      "spAttack": 55,
      "spDefense": 65,
      "speed": 45
    }
  },
  {
    "no": 77,
    "name": "ポニータ",
    "abilities": ["にげあし", "もらいび"],
    "stats": {
      "hp": 50,
      "attack": 85,
      "defense": 55,
      "spAttack": 65,
      "spDefense": 65,
      "speed": 90
    }
  },
  {
    "no": 78,
    "name": "ギャロップ",
    "abilities": ["にげあし", "もらいび"],
    "stats": {
      "hp": 65,
      "attack": 100,
      "defense": 70,
      "spAttack": 80,
      "spDefense": 80,
      "speed": 105
    }
  },
  {
    "no": 79,
    "name": "ヤドン",
    "abilities": ["どんかん", "マイペース"],
    "stats": {
      "hp": 90,
      "attack": 65,
      "defense": 65,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 15
    }
  },
  {
    "no": 80,
    "name": "ヤドラン",
    "abilities": ["どんかん", "マイペース"],
    "stats": {
      "hp": 95,
      "attack": 75,
      "defense": 110,
      "spAttack": 100,
      "spDefense": 80,
      "speed": 30
    }
  },
  {
    "no": 81,
    "name": "コイル",
    "abilities": ["じりょく", "がんじょう"],
    "stats": {
      "hp": 25,
      "attack": 35,
      "defense": 70,
      "spAttack": 95,
      "spDefense": 55,
      "speed": 45
    }
  },
  {
    "no": 82,
    "name": "レアコイル",
    "abilities": ["じりょく", "がんじょう"],
    "stats": {
      "hp": 50,
      "attack": 60,
      "defense": 95,
      "spAttack": 120,
      "spDefense": 70,
      "speed": 70
    }
  },
  {
    "no": 83,
    "name": "カモネギ",
    "abilities": ["するどいめ", "せいしんりょく"],
    "stats": {
      "hp": 52,
      "attack": 90,
      "defense": 55,
      "spAttack": 58,
      "spDefense": 62,
      "speed": 60
    }
  },
  {
    "no": 84,
    "name": "ドードー",
    "abilities": ["にげあし", "はやおき"],
    "stats": {
      "hp": 35,
      "attack": 85,
      "defense": 45,
      "spAttack": 35,
      "spDefense": 35,
      "speed": 75
    }
  },
  {
    "no": 85,
    "name": "ドードリオ",
    "abilities": ["にげあし", "はやおき"],
    "stats": {
      "hp": 60,
      "attack": 110,
      "defense": 70,
      "spAttack": 60,
      "spDefense": 60,
      "speed": 110
    }
  },
  {
    "no": 86,
    "name": "パウワウ",
    "abilities": ["あついしぼう", "うるおいボディ"],
    "stats": {
      "hp": 65,
      "attack": 45,
      "defense": 55,
      "spAttack": 45,
      "spDefense": 70,
      "speed": 45
    }
  },
  {
    "no": 87,
    "name": "ジュゴン",
    "abilities": ["あついしぼう", "うるおいボディ"],
    "stats": {
      "hp": 90,
      "attack": 70,
      "defense": 80,
      "spAttack": 70,
      "spDefense": 95,
      "speed": 70
    }
  },
  {
    "no": 88,
    "name": "ベトベター",
    "abilities": ["あくしゅう", "ねんちゃく"],
    "stats": {
      "hp": 80,
      "attack": 80,
      "defense": 50,
      "spAttack": 40,
      "spDefense": 50,
      "speed": 25
    }
  },
  {
    "no": 89,
    "name": "ベトベトン",
    "abilities": ["あくしゅう", "ねんちゃく"],
    "stats": {
      "hp": 105,
      "attack": 105,
      "defense": 75,
      "spAttack": 65,
      "spDefense": 100,
      "speed": 50
    }
  },
  {
    "no": 90,
    "name": "シェルダー",
    "abilities": ["シェルアーマー", "スキルリンク"],
    "stats": {
      "hp": 30,
      "attack": 65,
      "defense": 100,
      "spAttack": 45,
      "spDefense": 25,
      "speed": 40
    }
  },
  {
    "no": 91,
    "name": "パルシェン",
    "abilities": ["シェルアーマー", "スキルリンク"],
    "stats": {
      "hp": 50,
      "attack": 95,
      "defense": 180,
      "spAttack": 85,
      "spDefense": 45,
      "speed": 70
    }
  },
  {
    "no": 92,
    "name": "ゴース",
    "abilities": ["ふゆう"],
    "stats": {
      "hp": 30,
      "attack": 35,
      "defense": 30,
      "spAttack": 100,
      "spDefense": 35,
      "speed": 80
    }
  },
  {
    "no": 93,
    "name": "ゴースト",
    "abilities": ["ふゆう"],
    "stats": {
      "hp": 45,
      "attack": 50,
      "defense": 45,
      "spAttack": 115,
      "spDefense": 55,
      "speed": 95
    }
  },
  {
    "no": 94,
    "name": "ゲンガー",
    "abilities": ["のろわれボディ"],
    "stats": {
      "hp": 60,
      "attack": 65,
      "defense": 60,
      "spAttack": 130,
      "spDefense": 75,
      "speed": 110
    }
  },
  {
    "no": 95,
    "name": "イワーク",
    "abilities": ["いしあたま", "がんじょう"],
    "stats": {
      "hp": 35,
      "attack": 45,
      "defense": 160,
      "spAttack": 30,
      "spDefense": 45,
      "speed": 70
    }
  },
  {
    "no": 96,
    "name": "スリープ",
    "abilities": ["ふみん", "よちむ"],
    "stats": {
      "hp": 60,
      "attack": 48,
      "defense": 45,
      "spAttack": 43,
      "spDefense": 90,
      "speed": 42
    }
  },
  {
    "no": 97,
    "name": "スリーパー",
    "abilities": ["ふみん", "よちむ"],
    "stats": {
      "hp": 85,
      "attack": 73,
      "defense": 70,
      "spAttack": 73,
      "spDefense": 115,
      "speed": 67
    }
  },
  {
    "no": 98,
    "name": "クラブ",
    "abilities": ["かいりきバサミ", "シェルアーマー"],
    "stats": {
      "hp": 30,
      "attack": 105,
      "defense": 90,
      "spAttack": 25,
      "spDefense": 25,
      "speed": 50
    }
  },
  {
    "no": 99,
    "name": "キングラー",
    "abilities": ["かいりきバサミ", "シェルアーマー"],
    "stats": {
      "hp": 55,
      "attack": 130,
      "defense": 115,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 75
    }
  },
  {
    "no": 100,
    "name": "ビリリダマ",
    "abilities": ["ぼうおん", "せいでんき"],
    "stats": {
      "hp": 40,
      "attack": 30,
      "defense": 50,
      "spAttack": 55,
      "spDefense": 55,
      "speed": 100
    }
  },
  {
    "no": 101,
    "name": "マルマイン",
    "abilities": ["ぼうおん", "せいでんき"],
    "stats": {
      "hp": 60,
      "attack": 50,
      "defense": 70,
      "spAttack": 80,
      "spDefense": 80,
      "speed": 150
    }
  },
  {
    "no": 102,
    "name": "タマタマ",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 60,
      "attack": 40,
      "defense": 80,
      "spAttack": 60,
      "spDefense": 45,
      "speed": 40
    }
  },
  {
    "no": 103,
    "name": "ナッシー",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 95,
      "attack": 95,
      "defense": 85,
      "spAttack": 125,
      "spDefense": 75,
      "speed": 55
    }
  },
  {
    "no": 104,
    "name": "カラカラ",
    "abilities": ["いしあたま", "ひらいしん"],
    "stats": {
      "hp": 50,
      "attack": 50,
      "defense": 95,
      "spAttack": 40,
      "spDefense": 50,
      "speed": 35
    }
  },
  {
    "no": 105,
    "name": "ガラガラ",
    "abilities": ["いしあたま", "ひらいしん"],
    "stats": {
      "hp": 60,
      "attack": 80,
      "defense": 110,
      "spAttack": 50,
      "spDefense": 80,
      "speed": 45
    }
  },
  {
    "no": 106,
    "name": "サワムラー",
    "abilities": ["じゅうなん", "すてみ"],
    "stats": {
      "hp": 50,
      "attack": 120,
      "defense": 53,
      "spAttack": 35,
      "spDefense": 110,
      "speed": 87
    }
  },
  {
    "no": 107,
    "name": "エビワラー",
    "abilities": ["するどいめ", "てつのこぶし"],
    "stats": {
      "hp": 50,
      "attack": 105,
      "defense": 79,
      "spAttack": 35,
      "spDefense": 110,
      "speed": 76
    }
  },
  {
    "no": 108,
    "name": "ベロリンガ",
    "abilities": ["マイペース", "どんかん"],
    "stats": {
      "hp": 90,
      "attack": 55,
      "defense": 75,
      "spAttack": 60,
      "spDefense": 75,
      "speed": 30
    }
  },
  {
    "no": 109,
    "name": "ドガース",
    "abilities": ["ふゆう"],
    "stats": {
      "hp": 40,
      "attack": 65,
      "defense": 95,
      "spAttack": 60,
      "spDefense": 45,
      "speed": 35
    }
  },
  {
    "no": 110,
    "name": "マタドガス",
    "abilities": ["ふゆう"],
    "stats": {
      "hp": 65,
      "attack": 90,
      "defense": 120,
      "spAttack": 85,
      "spDefense": 70,
      "speed": 60
    }
  },
  {
    "no": 111,
    "name": "サイホーン",
    "abilities": ["ひらいしん", "いしあたま"],
    "stats": {
      "hp": 80,
      "attack": 85,
      "defense": 95,
      "spAttack": 30,
      "spDefense": 30,
      "speed": 25
    }
  },
  {
    "no": 112,
    "name": "サイドン",
    "abilities": ["ひらいしん", "いしあたま"],
    "stats": {
      "hp": 105,
      "attack": 130,
      "defense": 120,
      "spAttack": 45,
      "spDefense": 45,
      "speed": 40
    }
  },
  {
    "no": 113,
    "name": "ラッキー",
    "abilities": ["しぜんかいふく", "てんのめぐみ"],
    "stats": {
      "hp": 250,
      "attack": 5,
      "defense": 5,
      "spAttack": 35,
      "spDefense": 105,
      "speed": 50
    }
  },
  {
    "no": 114,
    "name": "モンジャラ",
    "abilities": ["ようりょくそ", "リーフガード"],
    "stats": {
      "hp": 65,
      "attack": 55,
      "defense": 115,
      "spAttack": 100,
      "spDefense": 40,
      "speed": 60
    }
  },
  {
    "no": 115,
    "name": "ガルーラ",
    "abilities": ["はやおき", "きもったま"],
    "stats": {
      "hp": 105,
      "attack": 95,
      "defense": 80,
      "spAttack": 40,
      "spDefense": 80,
      "speed": 90
    }
  },
  {
    "no": 116,
    "name": "タッツー",
    "abilities": ["すいすい", "スナイパー"],
    "stats": {
      "hp": 30,
      "attack": 40,
      "defense": 70,
      "spAttack": 70,
      "spDefense": 25,
      "speed": 60
    }
  },
  {
    "no": 117,
    "name": "シードラ",
    "abilities": ["どくのトゲ", "スナイパー"],
    "stats": {
      "hp": 55,
      "attack": 65,
      "defense": 95,
      "spAttack": 95,
      "spDefense": 45,
      "speed": 85
    }
  },
  {
    "no": 118,
    "name": "トサキント",
    "abilities": ["すいすい", "みずのベール"],
    "stats": {
      "hp": 45,
      "attack": 67,
      "defense": 60,
      "spAttack": 35,
      "spDefense": 50,
      "speed": 63
    }
  },
  {
    "no": 119,
    "name": "アズマオウ",
    "abilities": ["すいすい", "みずのベール"],
    "stats": {
      "hp": 80,
      "attack": 92,
      "defense": 65,
      "spAttack": 65,
      "spDefense": 80,
      "speed": 68
    }
  },
  {
    "no": 120,
    "name": "ヒトデマン",
    "abilities": ["はっこう", "しぜんかいふく"],
    "stats": {
      "hp": 30,
      "attack": 45,
      "defense": 55,
      "spAttack": 70,
      "spDefense": 55,
      "speed": 85
    }
  },
  {
    "no": 121,
    "name": "スターミー",
    "abilities": ["はっこう", "しぜんかいふく"],
    "stats": {
      "hp": 60,
      "attack": 75,
      "defense": 85,
      "spAttack": 100,
      "spDefense": 85,
      "speed": 115
    }
  },
  {
    "no": 122,
    "name": "バリヤード",
    "abilities": ["ぼうおん", "フィルター"],
    "stats": {
      "hp": 40,
      "attack": 45,
      "defense": 65,
      "spAttack": 100,
      "spDefense": 120,
      "speed": 90
    }
  },
  {
    "no": 123,
    "name": "ストライク",
    "abilities": ["むしのしらせ", "テクニシャン"],
    "stats": {
      "hp": 70,
      "attack": 110,
      "defense": 80,
      "spAttack": 55,
      "spDefense": 80,
      "speed": 105
    }
  },
  {
    "no": 124,
    "name": "ルージュラ",
    "abilities": ["どんかん", "よちむ"],
    "stats": {
      "hp": 65,
      "attack": 50,
      "defense": 35,
      "spAttack": 115,
      "spDefense": 95,
      "speed": 95
    }
  },
  {
    "no": 125,
    "name": "エレブー",
    "abilities": ["せいでんき"],
    "stats": {
      "hp": 65,
      "attack": 83,
      "defense": 57,
      "spAttack": 95,
      "spDefense": 85,
      "speed": 105
    }
  },
  {
    "no": 126,
    "name": "ブーバー",
    "abilities": ["ほのおのからだ"],
    "stats": {
      "hp": 65,
      "attack": 95,
      "defense": 57,
      "spAttack": 100,
      "spDefense": 85,
      "speed": 93
    }
  },
  {
    "no": 127,
    "name": "カイロス",
    "abilities": ["かいりきバサミ", "かたやぶり"],
    "stats": {
      "hp": 65,
      "attack": 125,
      "defense": 100,
      "spAttack": 55,
      "spDefense": 70,
      "speed": 85
    }
  },
  {
    "no": 128,
    "name": "ケンタロス",
    "abilities": ["いかく", "いかりのつぼ"],
    "stats": {
      "hp": 75,
      "attack": 100,
      "defense": 95,
      "spAttack": 40,
      "spDefense": 70,
      "speed": 110
    }
  },
  {
    "no": 129,
    "name": "コイキング",
    "abilities": ["すいすい"],
    "stats": {
      "hp": 20,
      "attack": 10,
      "defense": 55,
      "spAttack": 15,
      "spDefense": 20,
      "speed": 80
    }
  },
  {
    "no": 130,
    "name": "ギャラドス",
    "abilities": ["いかく"],
    "stats": {
      "hp": 95,
      "attack": 125,
      "defense": 79,
      "spAttack": 60,
      "spDefense": 100,
      "speed": 81
    }
  },
  {
    "no": 131,
    "name": "ラプラス",
    "abilities": ["ちょすい", "シェルアーマー"],
    "stats": {
      "hp": 130,
      "attack": 85,
      "defense": 80,
      "spAttack": 85,
      "spDefense": 95,
      "speed": 60
    }
  },
  {
    "no": 132,
    "name": "メタモン",
    "abilities": ["じゅうなん"],
    "stats": {
      "hp": 48,
      "attack": 48,
      "defense": 48,
      "spAttack": 48,
      "spDefense": 48,
      "speed": 48
    }
  },
  {
    "no": 133,
    "name": "イーブイ",
    "abilities": ["にげあし", "てきおうりょく"],
    "stats": {
      "hp": 55,
      "attack": 55,
      "defense": 50,
      "spAttack": 45,
      "spDefense": 65,
      "speed": 55
    }
  },
  {
    "no": 134,
    "name": "シャワーズ",
    "abilities": ["ちょすい"],
    "stats": {
      "hp": 130,
      "attack": 65,
      "defense": 60,
      "spAttack": 110,
      "spDefense": 95,
      "speed": 65
    }
  },
  {
    "no": 135,
    "name": "サンダース",
    "abilities": ["ちくでん"],
    "stats": {
      "hp": 65,
      "attack": 65,
      "defense": 60,
      "spAttack": 110,
      "spDefense": 95,
      "speed": 130
    }
  },
  {
    "no": 136,
    "name": "ブースター",
    "abilities": ["もらいび"],
    "stats": {
      "hp": 65,
      "attack": 130,
      "defense": 60,
      "spAttack": 95,
      "spDefense": 110,
      "speed": 65
    }
  },
  {
    "no": 137,
    "name": "ポリゴン",
    "abilities": ["トレース", "ダウンロード"],
    "stats": {
      "hp": 65,
      "attack": 60,
      "defense": 70,
      "spAttack": 85,
      "spDefense": 75,
      "speed": 40
    }
  },
  {
    "no": 138,
    "name": "オムナイト",
    "abilities": ["すいすい", "シェルアーマー"],
    "stats": {
      "hp": 35,
      "attack": 40,
      "defense": 100,
      "spAttack": 90,
      "spDefense": 55,
      "speed": 35
    }
  },
  {
    "no": 139,
    "name": "オムスター",
    "abilities": ["すいすい", "シェルアーマー"],
    "stats": {
      "hp": 70,
      "attack": 60,
      "defense": 125,
      "spAttack": 115,
      "spDefense": 70,
      "speed": 55
    }
  },
  {
    "no": 140,
    "name": "カブト",
    "abilities": ["すいすい", "カブトアーマー"],
    "stats": {
      "hp": 30,
      "attack": 80,
      "defense": 90,
      "spAttack": 55,
      "spDefense": 45,
      "speed": 55
    }
  },
  {
    "no": 141,
    "name": "カブトプス",
    "abilities": ["すいすい", "カブトアーマー"],
    "stats": {
      "hp": 60,
      "attack": 115,
      "defense": 105,
      "spAttack": 65,
      "spDefense": 70,
      "speed": 80
    }
  },
  {
    "no": 142,
    "name": "プテラ",
    "abilities": ["いしあたま", "プレッシャー"],
    "stats": {
      "hp": 80,
      "attack": 105,
      "defense": 65,
      "spAttack": 60,
      "spDefense": 75,
      "speed": 130
    }
  },
  {
    "no": 143,
    "name": "カビゴン",
    "abilities": ["めんえき", "あついしぼう"],
    "stats": {
      "hp": 160,
      "attack": 110,
      "defense": 65,
      "spAttack": 65,
      "spDefense": 110,
      "speed": 30
    }
  },
  {
    "no": 144,
    "name": "フリーザー",
    "abilities": ["プレッシャー"],
    "stats": {
      "hp": 90,
      "attack": 85,
      "defense": 100,
      "spAttack": 95,
      "spDefense": 125,
      "speed": 85
    }
  },
  {
    "no": 145,
    "name": "サンダー",
    "abilities": ["プレッシャー"],
    "stats": {
      "hp": 90,
      "attack": 90,
      "defense": 85,
      "spAttack": 125,
      "spDefense": 90,
      "speed": 100
    }
  },
  {
    "no": 146,
    "name": "ファイヤー",
    "abilities": ["プレッシャー"],
    "stats": {
      "hp": 90,
      "attack": 100,
      "defense": 90,
      "spAttack": 125,
      "spDefense": 85,
      "speed": 90
    }
  },
  {
    "no": 147,
    "name": "ミニリュウ",
    "abilities": ["だっび"],
    "stats": {
      "hp": 41,
      "attack": 64,
      "defense": 45,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 50
    }
  },
  {
    "no": 148,
    "name": "ハクリュー",
    "abilities": ["だっび"],
    "stats": {
      "hp": 61,
      "attack": 84,
      "defense": 65,
      "spAttack": 70,
      "spDefense": 70,
      "speed": 70
    }
  },
  {
    "no": 149,
    "name": "カイリュー",
    "abilities": ["せいしんりょく"],
    "stats": {
      "hp": 91,
      "attack": 134,
      "defense": 95,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 80
    }
  },
  {
    "no": 150,
    "name": "ミュウツー",
    "abilities": ["プレッシャー"],
    "stats": {
      "hp": 106,
      "attack": 110,
      "defense": 90,
      "spAttack": 154,
      "spDefense": 90,
      "speed": 130
    }
  },
  {
    "no": 151,
    "name": "ミュウ",
    "abilities": ["シンクロ"],
    "stats": {
      "hp": 100,
      "attack": 100,
      "defense": 100,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 100
    }
  }
]
```