唐突にダイスの期待値を計算するツールが欲しくなったから1週間で作ってリリースした part2

**この記事はpart2です！！part1を読んでない人は先にpart1を読んだ方が楽しめると思います😀**

▼ part1 ▼

https://qiita.com/cp20/items/b475b6f6757be814846f

## 完成品どーん(2回目)

https://dicespec.vercel.app/

## 前回のあらすじ

- ダイスの期待値求めてくれるサービスがないから作ることにした！
- せっかくだから他にも機能を付けることにした！
    - 「ダイスロール」と「CCFOLIA出力」
- 前回は「ダイス予測」を作った！

この記事では「ダイスロール」と「CCFOLIA出力」を作っていく過程を解説していくよ。

## ダイスロール

▼ 完成図 ▼

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/bf873c46-81eb-09e6-f0f7-52b3c7db370f.png)

このサービスの目標は「BCDiceを使ってダイスが振れる」ということ。そのためにまずはBCDiceのお勉強から始めることにする。

BCDiceというのはTRPGのダイスを振るためのRuby製OSSツールで、100以上のシステムに対応しており、CCFOLIAやTRPGスタジオといったセッションツールに搭載されている。BCDice APIというREST APIサーバー(のソースコード)が公式で提供されている。有志によってホストされているものがいくつかあるので今回はそれを利用させていただこうと思う。

### BCDice API

v2APIの仕様は以下のページにまとめられている。

https://github.com/bcdice/bcdice-api/blob/master/docs/api_v2.md

ダイスを振るためにはゲームシステムのIDが必要で、ゲームシステムのIDを得るためにはゲームシステムのID一覧にアクセスする必要がある、がここではいったん省略してダイスを振る部分を先に解説していく。

ダイスを振るエンドポイントは`/v2/game_system/{id}/roll`なのでその部分を掘り下げていこうと思う。

### 引数

パラメータ  | 種別        | 例         | 説明
--------- | -----       | -----     | -----
`{id}`    | URLに埋め込む | `Gorilla` | ゲームシステムのID
`command` | GET/POSTパラメータ | `4d10>=15` | コマンドの文字列

### レスポンス例

```json
{
  "ok": true,
  "text": "(4D10>=15) ＞ 25[8,3,5,9] ＞ 25 ＞ 成功",
  "secret": false,
  "success": true,
  "failure": false,
  "critical": false,
  "fumble": false,
  "rands": [
    {
      "kind": "normal",
      "sides": 10,
      "value": 8
    },
    {
      "kind": "normal",
      "sides": 10,
      "value": 3
    },
    {
      "kind": "normal",
      "sides": 10,
      "value": 5
    },
    {
      "kind": "normal",
      "sides": 10,
      "value": 9
    }
  ]
}
```

いろいろ情報が含まれてるが、ダイス結果を表示したいだけなので今回は`ok`、`text`、`success`、`failure`、`critical`、`fumble`だけ使うことにする。ユーザーから受け取った入力をAPIに渡して結果を受け取ったら、`text`を`success`、`failure`、`critical`、`fumble`に応じた色で表示させるようなプログラムを目標とする。

とりあえずダイスを振るプログラムがこんな感じ

```ts
fetch(`${config.apiServer}/v2/game_system/${config.system.id}/roll?command=${encodeURI(formatedInput)}`)
.then((res) => res.json())
.then((res: BCDice.DiceRollResponse): diceRollResult | errorResult => {
  if (res.ok) {
    return {
      success: true,
      result: res,
    };
  } else {
    return {
      success: false,
    };
  }
})
.catch((err) => {
  console.error(err);

  toast({
    title: t('errors.notFound'),
    status: 'error',
    isClosable: true,
  });
  return {
    success: false,
  };
}),
```

特別なことをしているわけではないので割と分かりやすいとは思う。

また、ここでダイスを振るのに必要なシステム名は`/v2/game_system`で一覧を取得できる。システムごとの詳細情報は`v2/game_system/{id}`で取得できる。

これを使って下のようなシステム選択のUIを実装した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/44e36d75-67eb-ba8e-2cc2-edd5a7062b92.png)

基本はChakra UIを使ってデザインを組み立てているのだが、Chakra UIにいい感じのセレクトボックスがなかったのでこれは自分でいい感じのものをこしらえた。詳しくはソースコードを読んで頂ければと(汚いのはゆるして...)

https://github.com/cp-20/Dice-Spec/blob/main/src/components/ui/Select/index.tsx

## CCFOLIA出力

▼ 完成図 ▼

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/782e0303-cd0d-e8c2-df4d-e47c95b81891.png)

なんか2つだけだと寂しいし適当に機能つけ足しとくか的な思考で生み出されたもの。でも実装が意外と面倒で1日ぐらいかかった。

特筆すべき事項は全然ないが、せっかくなのでクリップボードからの読み込み・クリップボードへの書き込みについて解説しようと思う。

### クリップボードから読み込み

```ts
if (navigator.clipboard) {
  navigator.clipboard.readText().then((text) => {
    console.log(`Your clipboard is "${text}"`);
  });
}
```

### クリップボードへの書き込み

```ts
const str = 'クリップボードに書き込む内容';
if(navigator.clipboard){
  navigator.clipboard.writeText(str).then(() => {
    console.log('Copied!');
  });
}
```

ただしこれはClipboard APIという新しめの機能を使う方法なのであまり後方互換性はよくない。2022年6月28日時点の対応状況は以下の表を参照。メジャーなブラウザはだいたいサポートしているのであまり気にせずに使えるだろうと思う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1909155/178e3bfa-7370-a991-231d-9e183c1db9ae.png)

▼ 参考記事 ▼

https://qiita.com/butakoma/items/642c0ec4b77f6bb5ebcf

https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API

(最新のブラウザの対応状況はこのサイトを参照)

## おわりに

今回内容がうすうすだった気がします。それはそれとしてダイススペックは頑張って作ったので気になったら使ってみてください。

https://dicespec.vercel.app/

次partはダイス予測のアプデについて書こうと思います。気長にお待ちくださいな。

2022/8/16追記
part3書きました。ダイス予測のアルゴリズムを改善するお話です。

https://qiita.com/cp20/items/89aa69111d631e8ac00f