エンジニアの上位20%のみが遊べるプログラミングタイピングゲームを作成した話

## はじめに
結構キャッチーなタイトルにしました。すみません。

エンジニア向けのプログラミングタイピングゲームに、上位 20 % のみが遊べる VIP ルームを作成しました。

https://untyping.jp/?from=qiita

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411258/fdcb1575-b589-71db-c6f5-f70562fe3516.png)

ぶっちゃけ、エンジニア以外の人も沢山プレイしていると思うので、エンジニアの上位 20 % というのは間違いですね。

是非、上位 20 % を目指して遊んでください。

## UnTyping とは
UnTyping は、以下の記事で紹介したプログラミング練習用のタイピングゲームです。

https://qiita.com/renesisu727/items/2eddd4f0eec80e3d5815


自分の感覚ではありますが、4000 点を超えると結構凄いです。

今回、こちらのプログラミング練習用のタイピングゲームに、世界ランキング上位 20 % のみが遊べる VIP ルームを作成しました。

## VIP ルームの難易度
VIP ルームは、UnTyping のトップ画面から移動できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411258/ae19f0d6-a2dc-e51c-6be1-ab47140f6966.png)

オープンルームで上位 20 % に入ったコースのみ、VIP ルームのコースを遊ぶことが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411258/4e8d0871-c1e4-3337-8817-2aecd71575a0.png)

各コードごとのオープンルームの制限時間は15秒ですが、VIPルームの制限時間は9秒です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411258/91e4a2f8-7a8c-cd37-c218-9b2c665c74ac.png)

VIP ルーム限定の長めのコードをタイピングすることになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411258/7887cc4a-e0eb-740c-4ea8-b42be8cfcb92.png)

VIP ルームの難易度は、**極めて高い**です。

全てのコードをタイピングするには、相当なタイピング能力が求められます。

VIP ルームを遊べるレベルの方でも、かなり苦戦することになるかと思います。

## VIP ルームを遊ぶ方法
ログインした状態で、オープンルームのコースを遊んでください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411258/8745417e-5e02-d044-fb20-31a19c70014d.png)

世界ランキング上位 20 % にランクインすれば、遊んだコースの VIP ルームが解放されます。

## VIP ルーム機能を作成した経緯
毎日UnTypingをプレイしている中で、スコアが伸び悩んでいることを感じていました。通常のJavaScriptコースでは、スコアが6000〜7000付近で停滞していました。

やはり「急かされながらタイピングする」状況が、タイピング速度を上げるためには重要だと考え、上級コースを作成することに決めました。

しかし、ただ上級コースを作成するだけでは気分が乗らないので、スマブラにちなんで、世界ランキング上位20％のみが挑戦できるVIPルームを作成することにしました。

全てのコースを VIP ルームに入れることを目指して、日々タイピングをしています。

## VIP ルームを遊んだ感想
VIP ルームのゲームをプレイしてから、明確にタイピング速度が速くなりました。

ただ、半分以上の文章を打ち逃すので、割とストレスが溜まります。

## VIP ルーム機能を作成した方法
UnTyping は、`T3-Stack`の構成で作成されています。

Userテーブルに `vipCourseIds` というカラムを追加し、VIPルームに入室する権利があるコースのIDを配列として保持することで実現しました。

```typescript
if (!user.vipCourseIds.includes(courseId)) {
  // vipCourseに登録する処理
  // 現在vipCourseに入っていない、かつVIPに入れるべきとき
  if (rankingResult.isVip) {
    const newVipCourseIds = [...user.vipCourseIds, courseId];
    // dbのvipCourseIdsを更新 
    void updateVipCourseIdsExecuter({ vipCourseIds: newVipCourseIds });

    // atomのvipCourseIdsを更新
    setSession((prevSession) => {
      if (!prevSession) return null; // sessionがnullの場合の処理

      return {
        ...prevSession,
        user: {
          ...prevSession.user,
          vipCourseIds: newVipCourseIds,
        },
      };
    });

    // VIP昇格のmodalを表示
    const isConfirmed = await openConfirmDialog(
      upgradeToVipModal(findOpenCourseCard(courseId).title),
    );

    //okAction でVIPページに遷移
    if (isConfirmed) {
      void router.push(ROUTES.VIP.url);
    }
  }
} 
```


ゲーム終了後にランキングを判定するAPIがあるため、そのAPIを改修し、VIPコースへの入室を許可するかどうかの判定を行うようにしました。

また、表示の際に VIP の資格が必要なページは、`layout` にラッパーコンポーネントを作成してリダイレクトを行いました。

```typescript
// VIPの資格が必要かどうか
const isRequireVipStatus = REQUIRE_VIP_STATUS_LIST(courseId).some(
  (path) => path === encodeURI(pathname),
);

// 資格が必要なページで、vipCourseIdsがなかったら、トップページへ飛ばす
if (isRequireVipStatus && !session?.user.vipCourseIds.length) {
  void router.push(ROUTES.INDEX.url);
  return <></>; // リダイレクト中は何も表示しない
}
```

## 終わりに
今回は、プログラミングタイピングゲーム**UnTyping**に VIP ルーム機能を追加した方法について紹介しました。

ぜひ、VIP ルーム入室を目指してゲームをプレイしてみて下さい。

お疲れさまでした。

https://untyping.jp/?from=qiita