【🀄️🀄️🀄️】React初学者が麻雀の点数計算サイトを作った話【ロン】

この記事は、[Ateam LifeDesign Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ateam-life-design) カレンダー3の22日目の記事です！

## はじめに
皆さん、こんにちは。@f0lstと申します！！
今回は**Reactの知識が0だった私**が、**麻雀の点数計算サイト**を作ったお話です🤞

## とりあえず見せてみぃ
というわけで、早速ですが、今回開発したサイトがこちら👇👇👇
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/1d62808f-a2f2-c3a2-afba-86a867831064.png" width="350">

https://mascor.jp/

## なんで作ったの？

ある日こんなことがありました。

同僚🤡「なあなあ、**雀荘**行ってみません？」
私🤖「行ったことない！！！行ってみましょ！！」

🀄️........🚶🚶🚶🚶

私🤖「あ...**麻雀ってゲームでしかやったことない**...**点数計算わからん**...」
私🤖「ま、いい感じのサイトあるだろー🥳」

🤖🤳
🤖🤳
🤖🤳
🤖🤳
...🤖🤳

私🤖「**わっかりにくいサイトしかねぇなあ！！！**」

⏰「...A FEW MONTHS LATER.」

上長🫡「来期から君はReactのPJだ」

私🤖「Reactやったことないけど、楽しそ！勉強せな！！」
私🤖「あ、そういえば、**使いやすい麻雀の点数計算サイトなかった**なぁ」
私🤖「状態管理とか基礎学べて良さそう...」
私🤖「**よっし！！作ろう！！！**」
私🤖「パチパチー🧑‍💻」

です。
~~このサイト作ってるうちに、**点数計算できるようになった**ことは内緒です🤫~~


## どんな機能があるの？

### ①点数計算機能
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/a97a940b-4863-e327-fcc3-6c9fbd8cc885.gif" width="350">

これが**このサイトで果たしたかった機能**です。
**余分な装飾なく、シンプルに点数を計算できるサイト**が目標だったため、
その目標は達成できたのでは...と思います🤟

#### 使い方
1. 親か子かを選択
2. ツモ、ロンどちらで上がったかを選択
3. 鳴いたかどうかを選択
4. 上がった役を一覧から選択
5. 点数が表示される

:::note
親と子、それぞれの支払う点数が表示されます🤞
:::

### ②役解説機能
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/0180f9bf-5bde-0491-6f01-ab62939960d3.png" width="350">

**1翻~タブル役満**までメジャーな役は**すべて画像つき**で解説しています！
また、**鳴きの可否や、鳴いた場合何翻になる**のかも補足しています。

**対局中このサイトがそばにあれば、点数計算もできるし、役の解説も見られる...**
なんと**素晴らしい**んでしょうか...！！！！！
~~役の解説と画像作るのが一番大変だったかもしれない🤫~~

:::note
最初は実装する予定はなかったのですが、「役解説機能欲しいよ😡！」とお声があったため、追加しました🫡
:::

## 工夫したポイント
### 工夫ポイント① 選べる役の制御👮‍♀️
まず、選択できる役の制御です。
以下が一例です。

#### 👮‍♀️ 鳴いた場合の制御
| 鳴いていない | 鳴いた |
| -- | -- |
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/bd112f55-9c6e-0267-1992-587fd43767b8.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/3a949b74-dd8e-fec2-cf34-6933ed813edd.png)|

グレーのボタンは非活性となっており、押すことができなくなっています。
鳴いている場合は、**立直や平和、一盃口の役は成立しない**ため、選択できません。

#### 👮‍♀️ あがり方による制御
| ロンあがり | ツモあがり |
| -- | -- |
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/c353c1bc-12a4-a63b-451c-4f65ee696a79.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/5d6c62c2-94f8-b50e-ded6-7e995239b3fe.png)|

**ロンあがり**の場合は、**ツモや嶺上開花は成立しない**ため、選択できません。
逆に、**ツモあがり**の場合は、**河底撈魚や槍槓は成立しない**ため、選択できません。

:::note
上記の例のように**子**、かつ**ツモあがり**の場合は、**親と子それぞれの支払う点数**が表示されます！
:::

#### 判定の基準

判定ポイントは以下の3点です。
- 親か子か
- ロンかツモか
- 鳴いたか否か

:::note
各役にstateを持たせ、役が選択されたり、鳴いたかどうかなどのステータスが更新される度にチェックしています！
共存できない役の場合はstateを更新し、**disableに変更**しています！
※stateの管理には`Recoil`を使用
:::

### 工夫ポイント② 喰下がりの表示 🍜
| 鳴いていない | 鳴いた |
| -- | -- |
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/3e5e3274-d24d-c690-ad77-2070eaacd292.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/10ec2d86-67f3-231b-f6c0-935a2b4fd17b.png)|

鳴いている場合、役によっては**2翻→1翻**に喰い下がる場合があります。
この機能を持っているサイトは私がみた限り見当たらなかったため、導入しました。

こちらも、Recoilで鳴いたか否かのstateを持ち、鳴いているのみ表示させる仕様としています！

## 開発で意識したポイント
### ① アクセシビリティ
まずは**アクセシビリティ**です。
恥ずかしながら、今までアクセシビリティに疎く、知見が全くなかったのですが、
今回を機に学ぶことができました😢

#### ①-1 コントラスト
いずれの要素も**レベルAA**を達成する水準で作成しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/8ce3e382-f552-25d4-4f48-074e03e2289b.png" width="350">

:::note
WCAG2.1に以下の記述があるため、選択が制御されているボタンのみ、
コントラストの基準は達成していません！
> テキスト又は文字画像において、次の場合はコントラストの要件はない。アクティブではないユーザインタフェース コンポーネントの一部である
[達成基準 1.4.3 コントラスト (最低限)](https://waic.jp/docs/WCAG21/#contrast-minimum)
:::

#### ①-2 ターゲットのサイズ
いずれの要素も**44x44pxを超えるサイズ**で作成し、**レベルAAA**を達成しています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003760/d5d96a81-b069-dfe9-adc8-d61e59bf5830.png" width="350">

:::note
こちらも、WCAG2.1に以下の記述があるため、それに準拠する形です。
> ポインタ入力のターゲットのサイズが 44 × 44 CSS ピクセル以上である。ただし、以下の場合は例外とする。
> * 同等のものが存在する: そのターゲットと同等のリンク又はコントロールが同じページに 44 × 44 CSS ピクセル以上のサイズで存在する。
> * インラインである: そのターゲットが文中、又はテキストブロック内に存在する。
[達成基準 2.5.5 ターゲットのサイズ](https://waic.jp/docs/WCAG21/#target-size)
:::

### ② デザインシステム
今回作成した[かんたん麻雀点数計算](https://mascor.jp/)では、[Shopifyのデザインシステム](https://polaris.shopify.com/)を参考にさせていただきました。

私は今までデザインをやったことがなく、デザイナーが作ったカンプを組み込むのみでした...😢
今回、デザインシステムの重要性を学べたことは、開発人生において非常に良い学びになりました😢！

https://polaris.shopify.com/

## 使用技術
- React
- Next.js
- Tailwind CSS
- Netlify

## 苦労したポイント
苦労したポイントなんですが、**本当に全部**です。笑
圧倒的にスキルが足りなさすぎたので、とても苦労したのですが、
その中からピックアップしてお話しします！

### ① そもそもReactむずかった
今回、**この開発でほぼ初めてReactを扱った**ので、最初は苦労しました...
「カスタムhookよくわからんー」、「コンポーネントどうやって切ればいいのー」と、
とても頭を悩ませました。

ですが、Udemy見て、開発して、Udemy見て...と繰り返すうちに、だんだんわかることが増えてきて、
圧倒的にできることが増えてきました...😢
嬉しい...😢

ですが、パフォーマンス面ではまだまだ分からないことが多いので、
`useCallbak`や`useMemo`あたり、「**完全に理解した**」と言えるよう努力します🙏

### ② Recoilでの状態管理

Recoilも今回初めて使ったのですが、
初めは概念を理解するのにとても時間がかかりました...

「**atom**ってなに🥳？」「**Selector**ってー🥳？」状態でした...。

改めて考えると状態管理が必要なものは、数個しかないので、そこまで複雑ではなかったのかも...🤔？
今では、そもそものJS力が弱かったのかなあと思っています。

そんな中で色々切り分けながら実装し、なんとか実現できたものの、
**正直、現状の実装がベストなのかわかっていません！笑
~~絶対~~ベストではないでしょう！笑**

ですが、これは今後の伸びしろのためです！！！
近い将来、「これが最強ダゼ🤟」って状態にしてみます！！

## まとめ

さて、まとめです。
めちゃくちゃ当たり前なのですが、本当にやってよかったと心から思います🤞
このサイト制作をやる前、やった後を比較してみると多くのことができるようになったなぁと思います。

### 💻 スキル面 💻
- 🙅 **React, Next.jsの知識が0**で学ぼうとも思っていなかった
  - 🙆 Reactの**基礎やおおよそのカスタムhookの知識**を身に付けられた
  - 🙆 Next.jsの**基礎やコンポーネントなどの知識**を身に付けられた
- 🙅 **ホスティングサービスってなに**？だった
  - 🙆 **Vercelのデプロイ**を知ることができた
  - 🙆 諸々調べて、最終**Netlifyを選定**し、**デプロイ**できた
- 🙅 **計測系ツール**の導入わからなかった
  - 🙆 以下、ツールを**自力で導入**できた
    - GA
    - GTM
    - SearchConsole
- 🙅 **デザイン**、ワタシ、**ワカリマセン**...
  - 🙆 **アクセシビリティ、デザインシステム**の知見を得られた
### 🫀 メンタル面 🫀
- 🙅 終業後は**YouTubeばかり見ていた**
  - 🙆 終業後に~~ほぼ~~毎日開発を行い、**学ぶ習慣**を身に付けられた
- 🙅 知識がないからと、**学ぶことから逃げていた**
  - 🙆 わからないなりにも、**徹底的に調べれば自分の力でなんとかなる**と知った
  - 🙆 **何事も成せばなる**と知った ←これ本当に大事
- 🙅 自分ひとりで何かを作り上げたことがなかった
  - 🙆 サイトをひとつ、作り上げることで**成功体験**ができた  

と、ざっくりあげても、**とっても多く学びがありました**！
とは言え、**まだまだ伸ばせるスキルは山積**ですし、**実力もまだまだ**です。
今後もスキルアップ重ねていき、フロントエンジニアと自信を持って言えるようにします🤟🤟🤟

## 最後に
いよいよ、アドベントカレンダーも大詰めです！
今後、どんな記事が上がるのかとても楽しみですね🕺🕺🕺
私もウキウキして待ちたいと思います🤞
最後まで見ていただき、ありがとうございましたー！