ツンデレ湯婆婆はReactで色恋するのか？

# あらすじ

みなさま、お腹いっぱいでしょうか？
「湯婆婆ネタはもういらない」と？
いまさら感が強いですが、またまた湯婆婆~~のラブコメ~~と学ぶ入門記事です。

[湯婆婆ブーム](https://qiita.com/torifukukaiou/items/c8361231cdc56e493245)もそろそろ落ち着いてきましたね。
[Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2)が元ネタです。

# 難易度☆★★★★

書いたコードの難易度としては、
[Progate](https://prog-8.com)の[Reactコース](https://prog-8.com/languages/react)修了レベルです。
やはり湯婆婆は入門者の[ゲーミフィケーション](https://ferret-plus.com/6840)に最適ですね。

# 相違点

Reactは既に「[React (JavaScript) で湯婆婆を実装してみる](https://qiita.com/drytt/items/250440366c9f72f619dd)」で紹介されています。
後発として差別化をします。

- BabelではなくTypeScriptを使用
- CodePen.ioで形成した湯婆婆を埋め込み
- 書き終えた契約書はReactiveに瞬間移動し湯婆婆の手の中へ
- 契約書はQiitaカラー`#55c500`にして統一感を演出

# 恋する乙女、ツンデレ湯婆婆ちゃん

<p class="codepen" data-height="400" data-theme-id="light" data-default-tab="js,result" data-user="ShortArrow" data-slug-hash="XWKGmVM" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="React-Yubaba">
  <span>See the Pen <a href="https://codepen.io/ShortArrow/pen/XWKGmVM">
  React-Yubaba</a> by ShortArrow (<a href="https://codepen.io/ShortArrow">@ShortArrow</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

### 言語による冷静な事務対応の限界

２つの言語を試してみて、気が付いたことがあります。
どの時点まで**𠮷**田さんに冷静に対応できるのか？
それが言語によって「簡単に調節できるか」が異なるのです。

以前書いた記事「[Powershellで湯婆婆の召喚魔法を実装](d39a5f0682603bd150ee.md)」では、
Powershellでした。

```text
契約書だよ。そこに名前を書きな。
��田
フン。��というのかい。贅沢な名だねぇ。
今からお前の名前は��。いいかい、��よ。分かったら返事をするんだ、、�!�!!
```

この時の湯婆婆ちゃんは、
契約書に記載した**𠮷**田という正式名すら発声できません。
それどころか視界不良に陥り、契約書が見えていないようです。
**「デレデレ」** 過ぎてこっちが恥ずかしいですね。

### ツンデレ湯婆婆ちゃん

今回の湯婆婆ちゃんは、Javascriptです。
**𠮷**田さんという名前を発声することができました。

```text
フン。𠮷田というのかい。贅沢な名だねぇ。
```

ここまでは **「ツン」** ですね。
ところがその直後、自分で考えたニックネームを発声できません。

```text
今からお前の名前は�だ。いいかい、�だよ。分かったら返事をするんだ、�!!
```

恥ずかしくて **「デレ」** ています。

**「アオハルかよ」**って感じですね。
挿絵として**「少女漫画風の湯婆婆」**が欲しいです。

# 冷静な事務対応を執行するには

### 湯婆婆ちゃんを失恋させる

湯婆婆ちゃんを失恋させるにはサロゲートペアを考慮する必要がありました。
[なぜ絵文字を含む文字を1文字ずつに分けるのにArray.fromだけで十分なのか？](https://qiita.com/alucky0707/items/697598e49ff56191c139)
という記事で詳細に解説されています。

また、[Flutterの湯婆婆にサロゲートペア文字を理解させたら可愛くなった💗](https://qiita.com/simontanz/items/690fb1b22ac75410d87e)で紹介されていますが、
Dartの場合Charactersクラスを使って簡単に処理することが出来るそうです。

※サロゲートという言葉の語感は、[石黒研究室](https://www.irl.sys.es.osaka-u.ac.jp/)のサロゲートが出演する[サロゲート](https://www.amazon.co.jp/%E3%82%B5%E3%83%AD%E3%82%B2%E3%83%BC%E3%83%88-DVD-%E3%83%96%E3%83%AB%E3%83%BC%E3%82%B9%E3%83%BB%E3%82%A6%E3%82%A3%E3%83%AA%E3%82%B9/dp/B003CF2MRY)という映画をご覧いただくと理解しやすいと思います。

### 湯婆婆失恋バージョン

<p class="codepen" data-height="400" data-theme-id="light" data-default-tab="js,result" data-user="ShortArrow" data-slug-hash="ZEOZrBj" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="React-Yubaba-LostLove">
  <span>See the Pen <a href="https://codepen.io/ShortArrow/pen/ZEOZrBj">
  React-Yubaba-LostLove</a> by ShortArrow (<a href="https://codepen.io/ShortArrow">@ShortArrow</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

失恋バージョンでは`handleClick()`を書き換えています。

```react
handleClick() {
	const randamIndex = Math.round(Math.random() * (Array.from(this.state.name).length - 1));
	const madeName = Array.from(this.state.name)[randamIndex];
	this.setState({
		clicked: true,
		handleName: madeName
	});
}
```

恋する乙女バージョンでは`this.state.name`の`length`プロパティから長さを取得していました。
これを`Array.from()`で配列化してから長さを見るようにしています。

また、`substring()`を使って切り出していたところを、配列のインデックスで指定して取り出すように変えました。

### 失恋バージョンへの入力

**𠮷**田さんのほうから、アプローチを仕掛けてみましょう。
ちょっとハートマークが騒がしいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/a0ae972a-d33d-47ad-1493-b6d3bc81c21b.png)

### 失恋バージョンの結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/9b148554-1b26-6096-a2e5-d8336ef8e553.png)


この通り、全く緊張感の欠片もありません。
淡々と機械的に読み上げる様を見る限り、
微塵も恋している様子はありませんね。

# 添え字の境界値に気を付けよう

境界値に気を付けなければ、以下の等式が成り立つ恐れがあります。

```text
1 ÷ (名前の長さ + 1) = 湯婆婆が絶句する確率
```

下記の`handleClick()`は湯婆婆の名前を盗むロジックのコアです。
この中で、`(this.state.name.length - 1)`として配列の添え字の番号に合わせています。

```react
handleClick() {
	const randamIndex = Math.round(Math.random() * (this.state.name.length - 1));
	const madeName = this.state.name.substring(randamIndex, randamIndex + 1);
	this.setState({
		clicked: true,
		handleName: madeName
	});
}
```

仮に、`randamIndex`の定義が、

```react
const randamIndex = Math.round(Math.random() * this.state.name.length);
```

だとしましょう。

`Math.random()`で0～1の範囲を作り出しています。
その結果、名前が`御成敗式目`の場合に`randamIndex`の値は0～5となります。
そうすると、`randamIndex`の値が0の時は`madeName`が`御`で、4の時は`madeName`が`目`です。

そうなんです。`randamIndex`が5になれば、`madeName`の値はヌル文字列です。

やはり、添え字に気を付けて「マイナス１」をするのは大切です。

# 環境設定

CodePen.ioで書いています。

## CodePen.ioでの設定内容

- 下記CDNでReactをインポート
  - <https://unpkg.com/react@17/umd/react.development.js>
  - <https://unpkg.com/react-dom@17/umd/react-dom.development.js>
- ドロップダウンボックスでTypeScriptを選択
- その他はデフォルト設定

# まとめ

多言語でも同じ方法で失恋させることが出来る場合とそうでない場合がありそうです。
この記事を読んで「別の言語で失恋をさせてみたいな」と感じてもらえたらハッピーです。

**Excelsior!**