見出し画像

抽選ツールをv0を使って作ってみた

この記事は モニクル Advent Calendar 2024の23日目の記事です。


はじめに

年末と言えば忘年会!忘年会と言えば豪華賞品を懸けた抽選会!ということで、オンラインでサッと使える抽選ツールをv0を使って作ってみました。
広告なし、サーバへのデータ保存なし、なので気軽に使用できます!

この記事では、作成した抽選ツールの紹介とともに、v0を使った一連の作成の流れを説明して行きます。

抽選ツールについて

URL

作成した抽選ツールのURLは https://lottery.itaosan.dev/  です。

使い方

はじめに、抽選設定画面でタイトルや賞の名前、当選発表までの秒数、参加者リストを入れます。その後、設定を保存すると抽選画面に遷移します。
設定情報はテキスト形式でエクスポート、インポートができるので、事前に抽選の内容を作っておいて、ローカルに保存しておく事が出来ます。

参加者リストで重み付けを行うことが出来ます

抽選画面では、抽選開始ボタンを押すと、賞の名前に入れた順に1つずつ抽選が行われます。

参加者リストで設定した倍率も表示されています

名前がランダムに表示され・・・

ドラムロールが鳴ります

ファンファーレと共に当選者発表です!

おめでとうございます!

当選者一覧が下部にでます。一度当選した人は参加者一覧からは除外されます。

複数の賞を抽選する時に当選者の一覧も見ることができます

v0を使った作成の流れ

この抽選ツールですが、v0という生成AIを使い、コードを生成してもらいました。
ツールを作っていく中での気づいたことや注意点も加えながら、以下に作成の流れを記載していきます!

v0とは

Vercelの「v0」は、AIを活用してユーザーの自然言語入力からウェブサイトやアプリケーションのUIを自動生成するツールです。これにより、直感的に高品質なUIを作成できます。
主にUIを作成する時のツールと説明がありますが、データベースとの通信が発生しない、フロントのみで完結するサイトを作る場合でも有効に使う事が出来ます。

v0はあなたの常時ペアプログラマーです。 最新のウェブテクノロジーに関する深い知識を持ったジェネレーティブなチャットインターフェイスです。 ウェブ上でのビルド中に技術的なガイダンスを提供したり、クライアントサイドの機能でUIを生成したり、JavaScriptやPythonでコードを書いて実行したり、複雑なプログラミングのトピックを説明するダイアグラムを作成したりすることができます。

https://v0.dev/faq より

ChatGPTで要件定義

まずは作りたいサイトの要件をまとめて、それをv0のプロンプトへ渡します。
v0に限らず、生成AIを使用する場合にはAIが理解しやすい、なるべく正確な言葉で具体的な指示を出すのが良いとされています。
(一般的なシステム開発でも同じですね!)
餅は餅屋という事で、v0に出す要件定義のプロンプト文はChatGPTに相談して作ってもらう事にしました。

ChatGPTに雑に相談
追加の要望も挙げたりする

上記のようなやり取りを繰り返して、v0に送る用のプロンプト文を下記のように作りました。

忘年会で使う抽選ツールを作成したいです。
参加者の一覧からランダムで1名を抽出し、当選者として表示します。
参加者が楽しめるような視覚効果やサウンドを付けた抽選ツールにしたいです。
以下が必要な画面と機能です

# 機能概要
- 参加者一覧をスロットのリールのように回転させ、ランダムに1名を抽選するツールを作成したい。
- 一部の参加者に当選確率を優遇する機能を追加したい。

# 動作イメージ
- 抽選画面上のリール(リスト)が上下に回転する。
- 回転速度は最初速く、徐々に遅くなる(慣性のある動き)。
- 回転が停止するとき、選ばれた1人が中央または目立つ位置に表示される。
- 当選確率の優遇により、特定の参加者が選ばれやすくなる。

# 画面の構成
- 1920×1200の解像度を最大限利用した大きな画面構成
# 参加者一覧
- 参加者はテキストファイルや入力フォームで改行区切りで指定される
- 特定の参加者には「倍率」を指定できるようにする。
	- 名前の後ろにカンマで倍率を指定
	- 倍率が未指定の場合はデフォルトで1とみなす
	- フォーマット例:
```
山田太郎,10
佐藤花子,1
鈴木一郎,1
```

# 抽選画面
- 抽選画面の下部に抽選開始ボタンを置き、それを押すことで抽選のアニメーションと抽選が開始
- 設定画面で設定された秒数後に当選者を決定
- 抽選中はドラムロールのサウンドを鳴らす
- 視覚的にスムーズで魅力的なアニメーション。
- スロットのリールのように複数行が見える(例: 3行同時に表示)。
- フォントやカラーは柔軟にカスタマイズできるようにする。

# 当選者発表
- 当選者が決定したら別のダイアログで中央に大きく当選者の名前を表示する
- ファンファーレや視覚的な効果も入れて特別感を演出する
- ダイアログのOKボタンを押すと、当選者は当選者一覧に表示し、参加者一覧から当選者の行を消す
- 以降続けて抽選を行えるようにする

# 設定画面
- 下記の設定が行えるようにする
- 抽選のタイトル
	- 入力された内容をタイトルとして表示する
- 当選発表までの秒数
	- デフォルト15秒でリールが回り始めてからストップするまでの秒数を設定

# **確率計算の仕組み**
- 入力された倍率を元に、内部で抽選のリストを動的に生成する。
    - 例: 上記のリストでは「山田太郎」が10回、「佐藤花子」と「鈴木一郎」がそれぞれ1回ずつリストに追加される。
    - 結果として、当選確率は以下のようになる:
        - 山田太郎: 10/1283.3%
        - 佐藤花子: 1/128.3%
        - 鈴木一郎: 1/128.3%
- このリストを元にスロットリールの回転や抽選を行う。

# **UIおよびアニメーションの要望**
- 優遇された人の倍率によってアニメーションの挙動が変わらないようにする。
- リールの見た目はあくまで均一で、倍率の効果は裏側のロジックでのみ反映する。

v0でコード生成&はじめての動作確認

プロンプト文をv0に張り付けてみると、下記のような感じでプロトタイプを作ってくれました。画面右側では出力されたコードを確認したり、その場で動作確認を行う事が出来ます。

v0がコード生成と共に説明もしてくれます
出力されたコード

ただ、動作確認すると抽選はしてくれるものの、あまりうまく動いてくれません。

イメージと違う・・・

ここからは、v0と指示をやり取りして自分のイメージに近づけていきます。また、追加したい機能や動作なども付け加えていきます。
これがv0の特徴の一つである対話型デザインです。

対話をしながら改善して行く

あたかもプログラマーと会話するかのように、改善点や希望する動作を伝えていきます。
下図のように指示を出す度にコードが修正され、即動作確認が可能になるので、動きを見ながら作り上げていきます。

v0と一緒に作っていきます
議論が白熱して途中からv0の回答が英語になっています

うまくいかない動作をあきらめる

何度かやり取りしましたが、当初目指していたスロットのリールのような動きがどうしてもうまくいかず、ランダムで表示が切り替わる方法に仕様変更をしました。

スロットリール最終版の動作
なめらかなストップモーションが再現できませんでした
残念な思いで仕様変更を伝えます
AIなのでこちらの心情は気にせず淡々と処理します

見た目の改善や機能追加を行う

仕様変更後、一通りの動作は確認できたものの抽選ツールとしてはいささかシンプルで盛り上がりに欠けるので、演出面を強化して行きます。また、テスト中に思いついた機能なども都度要求して行きます。

素晴らしいジャストアイデア(その場の思いつき)をどんどん依頼します
AIなのでこちらの心情は気にせず淡々と処理します

最終調整を行う

細かい動作変更は自分でコードの中身を見て、具体的に指示していきました。

微調整の段階ではコード内容について指示します

ローカルで動作確認&素材の投入

動作は完成しましたが、この状態では抽選時のドラムロールや当選発表時のファンファーレが鳴りません。というのも、v0で生成したコード上ではサウンドを鳴らす処理は入っているのですが、サウンドの音源ファイル自体は生成してくれなく、また、v0側へ素材ファイルをアップロードする事が出来ないのです。
そのため、一度ローカルへソースコードをダウンロードし、プロジェクト内に音声ファイルを入れて、最終的な動作確認を行う事にしました。

※v0で作られたコードを動かすためにはNode.jsの環境が必要になります

ローカル環境へのソースコード取得はv0の画面右上にある 「Add to Codebase」ボタンを押し、npx shadcn のコマンドをコピーしてローカル環境で実行する事でコード一式が取得できます。
shadcn/ui はReact や Next.js プロジェクトで使えるコンポーネントライブラリを生成するためのツールです。Tailwind CSS と Radix UI を活用しており、あらかじめスタイルが整った再利用可能な UI コンポーネントをプロジェクトにコピーして使える点が特徴です。
npx shadcn addコマンドで既存のUIコンポーネントのプロジェクトを取り込むことができます。

Add to Codebaseを押して…
npx shadcnでコードを取得

音声ファイルは効果音ラボ様、red bears様の音源を使用させていただきました。

Vercelにデプロイしてみる

v0で作成したものを公開したい場合、公開先がVercelであれば右上のDeployボタンより簡単にデプロイが可能です。
ただ、今回はローカルで別途音声ファイルを用意する必要があったり、Cloudflareで取得しているドメインをカスタムドメインとして使用したい、などの理由により、Cloudflare上にデプロイしています。

VercelへはDeployボタンから簡単にデプロイ可能

Cloudflareにデプロイしてみる

Cloudflare へのデプロイは、Cloudflare Pages へGitHubのリポジトリを接続する方法でデプロイしました。
npx shadcnで取得したソースをGitHubへPushした後、CloudflareのPagesより、作成 > Pages で、Gitに接続を行います。
詳しくはCloudflare PagesのGet startedを参照すると良いです

※注意点として、v0で生成されたプロジェクトはNode.jsで動作するものなので、Pagesのビルド設定で互換性フラグに nodejs_compat を設定する必要があります

Node.js互換モードで動作するように指定

完成!

これでv0を使って、抽選ツールをwebに公開するところまで出来ました!

いい感じに完成しました!

注意点や気づいたこと

一連の流れを通して、基本的に私はコードを1行も書くことが無く、抽選ツールを作成する事が出来ました!🎉
その際、いくつかの注意点や気づきがあったので下記に記載します。

v0のフリープランでの制限について

v0ではクレジットという単位の容量が存在し、v0に指示を行う度にクレジットが消費されます。クレジットが無くなるとそれ以降指示を出すことが出来なくなります。
2024年12月現在、フリープランの場合は月あたり200クレジットが使用可能となっています。
どのようにクレジットが消費されるかというのは、正確な記載は見つけられませんでしたが、1つの指示を行う度におおよそ10~30クレジットが消費されているようでした。
つまり、フリープランの場合1ヶ月に10~20回程度のやり取りしか行えないので、単純なUIや画面を生成してもらうだけならば十分ですが、今回のように繰り返し指示を出して調整していくような使い方をした場合には、明らかにクレジットが不足してしまいます。
月20ドルの課金を行う事で月のクレジット数が5000になるので、筆者は1ヶ月だけ課金を行いました。

詳しくは下記のPriceページを参照してください。

生成されたコードについて

生成されたコードをよく見ると、v0とのやり取りで機能を変更、修正していくうちに使わなくなった変数やimportなどがそのまま残っている状態でした。
プロトタイプとして見るだけでしたら特に問題は無いかと思いますが、今後も使用するような場合は、修正しておいた方が良いかと思います。

使用していないプロパティが残っている
コンポーネントを消してもらったけど、import文は残ったまま

最終調整の際の指示について

最終調整を行う際、言葉の指示だけだとなかなか理解してくれないケースがあり、無駄に何度もやり取りを行う事がありました。その際、細かい指示はコードの中身を見て具体的に指摘するとうまくいったので、こちら側も生成されたコードの中身を見て、ある程度は動作を理解できるようになる必要があるかと思いました。

ローカルに取り込んだ後に再度v0で修正を入れる場合

npx shadcn addでローカルにコードを取り込んだ後、手元で不要な変数やimport文などを削除したり、自分で微調整などしたりしてコードを修正した後に、v0に再度指示を出して修正して欲しくなった場合、生成するコードがv0上のコードベースに対して生成されるので、再度同じようにコードをローカルに取り込んで修正する必要があります。(うまく統合する方法があるのでしょうか?)

さいごに

新しい生成AIツールが登場すると、プログラム全く分からなくてもシステムを作ることができる!と言ったうたい文句が良く出てきますが、プログラムが全く分からない状態ではまだまだ難しいかなと感じました。
とはいえ、Next.jsやReact、shadcn/uiが未経験である筆者が数日でこのくらいのサイトを公開出来たというのは驚きでした!
今後も情報を集めて生成AIを上手に使っていきたいですね!

抽選ツールについては忘年会、新年会などでご自由にお使いください!


いいなと思ったら応援しよう!