3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TL; DR

  • Gemini CLIで共和暦の時計を作成

image.png

はじめに

今週突如として現れたGemini CLI。ソースコードがOSS公開されており、なにより無料で使えます(2025/06/29現在)。
というわけで、Claude Codeもまだ使いこなせていないのにホイホイつられて 流行りに乗って触ってみました。

腕試しということで、↓の条件に合う小さなツールがよさそうです。

  • Gemini CLIのサンドボックスでデフォルトで使える技術スタック(=Node.js)
  • 学習データに含まれていなさそうな 微妙に役に立たない 題材

そこで今回は、共和暦のカレンダーと時計を表示するWebアプリをVibe Codingで作成して(作成させて?)みました。

共和暦についておさらい

共和暦はフランス革命の際に作られた暦です。「テルミドールのクーデター」の「テルミドール」は共和暦の11番目の月です。
この暦の特徴として、時間に10進法を持ち込んだ点が挙げられます。

1日 10時間
1時間 100分
1分 100秒

メートル法等と異なり10年ほどで廃止されてしまいましたが、本記事ではこの暦をオンライン上に再現したいと思います。

作ったもの

アナログ時計とカレンダーです。1(共和暦)秒ごとに針が動きます。

image.png

うるう秒等の考慮はできていないので、あくまでジョークアプリとしてご利用ください。

実装

肝となるアナログ時計の実装は以下の部分です。

src/main.ts
  // ※オリジナルのコメント(Geminiが作成)は英語だったので、著者が日本語に翻訳

  const now = new Date();
  // Calculate total seconds from midnight in Gregorian time, including milliseconds for smoother movement
  const gregorianSecondsToday = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds() + now.getMilliseconds() / 1000;

  // 日数に変換したのち、共和暦の時間単位に変換
  const dayFraction = gregorianSecondsToday / 86400;
  const republicanHours = dayFraction * 10;
  const republicanMinutes = (republicanHours * 100) % 100;
  const republicanSeconds = Math.floor((republicanMinutes * 100) % 100);

  // 針(hand)の角度を計算
  // 時針: 10時間で 2*PI 回転
  const hourAngle = (republicanHours * (Math.PI / 5)) - (Math.PI / 2);
  // 分針: 100分で 2*PI 回転
  const minuteAngle = (republicanMinutes * (Math.PI / 50)) - (Math.PI / 2);
  // 秒針: 100秒で 2*PI 回転
  const secondAngle = (republicanSeconds * (Math.PI / 50)) - (Math.PI / 2);

00:00から経過したグレゴリオ暦(=普段私たちが使っている暦)での秒数を共和暦の経過秒数に変換し、再度時、分、秒に分割しています。

針の角度は弧度法で指定しています。
方向については、canvasの座標はy軸が上限反転しているため、値を増やすことで時計回りに進みます。

image.png

最後に、00:00のときは真上1に針があるので角度から $- \frac{\pi}{2}$ を引きます。

上記の処理が setTimeout で1(共和暦)秒ごとに呼び出されることで、時計の針が動いていきます。

src/main.ts
setInterval(() => {
  updateCalendar();
  drawClock();
}, 864); // 1日 = 86400(グレゴリオ暦)秒 = 100000共和暦秒なので、1共和暦秒 = 0.864(グレゴリオ暦)秒

Vibe Codingでの開発

Gemini CLIの開発環境

Gemini CLIには、安全に開発を行うためのサンドボックスモードが備わっています。

$ gemini -h
...
  -s, --sandbox                  Run in sandbox?                       [boolean]
      --sandbox-image            Sandbox image URI.                     [string]
...

サンドボックスを有効にすると、Gemini CLIはサンドボックスのDockerコンテナの中のみで作業を行います。誤って作業ディレクトリ外の必要なファイルを消してしまう心配はありません。Vibe Codingで確認なしでコマンドを実行させる際には使ったほうが安全です。

また、サンドボックス環境のDockerコンテナには、Gemini CLIを動かすためのNode.jsがプリインストールされています。そのため、Nodeで開発を行う場合はインストール等不要で開発を始められます2

サンドボックスに使用されるコンテナの中身
$ docker run -it --rm us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.1.5 bash
node@c6fa9ea6dac9:/$ node -v
v20.19.3
node@c6fa9ea6dac9:/$ npm -v
10.8.2

ただし、ネットワークをコンテナ外とつないでいないため、npm run dev によるアプリ起動はずっとハングした状態になります。いったん ESCでコマンドを止めて、コンテナ外で手動で実行しました。

Gemini CLIとのやり取り

最後に、開発風景としてGemini CLIとのやり取りを紹介します。
一度も具体的な実装方針については言及していませんが、不具合報告だけで要件をくみ取って実装を進めることができました。

プロンプト(1回目)

最初のプロンプト
viteを使用して、ブラウザ上に共和歴のアナログ時計を描画するwebサイトを構築してください。使用する技術は以下の通りです。

- TypeScript
- Vite

仕様

- 時計はアナログ
- カレンダーで日付も表示

共和暦の計算方法は一切説明しなかったのですが、自前で設計を考えほぼ完成系のコードが出力されました。正直時計の上側が 12 になったり一日を86400共和暦秒で計算したりすると思っていたので驚きです(驚き屋ノルマ達成)。

ただし、更新のタイミングが1(グレゴリオ暦)秒ごとで秒針が中途半端な位置に描画されていました。

kyouwareki1.png

  const decimalTime = (hours * 3600 + minutes * 60 + seconds) / 8640;

  const hourAngle = (decimalTime * 10) * (Math.PI / 5) - Math.PI / 2;
  const minuteAngle = ((decimalTime * 1000) % 100) * (Math.PI / 50) - Math.PI / 2;
  const secondAngle = ((decimalTime * 100000) % 100) * (Math.PI / 50) - Math.PI / 2;
setInterval(() => {
  updateCalendar();
  drawClock();
}, 1000);

プロンプト(2回目)

プロンプト
グレゴリオ暦の1秒ではなく共和暦の1秒ごとに針が動くようにしてください。

冒頭の実装通り、共和暦秒ごとに更新する実装に修正されました。一方、1秒以下の端数が角度に反映されて秒針の位置がずれてしまいました。

プロンプト(3回目)

プロンプト
秒は切り捨てにしてください。(時、分はそのままにしてください)

秒針がちょうどの位置に描かれるようになりました。厳密には1秒以下の遅れが発生していますが許容範囲とします3

- const republicanSeconds = (republicanMinutes * 100) % 100;
+ const republicanSeconds = Math.floor((republicanMinutes * 100) % 100);

想定する実装になったので、ここでGemini CLIを終了しました。
途中で寝落ちしたので経過時間が凄いことになっていますが、確認込みで実質15分くらいしか作業していません。

トークン消費量
> /quit

╭─────────────────────────────────────╮
│                                     │
│  Agent powering down. Goodbye!      │
│                                     │
│                                     │
│  Cumulative Stats (4 Turns)         │
│                                     │
│  Input Tokens              288,427  │
│  Output Tokens               6,197  │
│  Thoughts Tokens            23,866  │
│  ─────────────────────────────────  │
│  Total Tokens              318,490  │
│                                     │
│  Total duration (API)       4m 28s  │
│  Total duration (wall)  12h 1m 20s  │
│                                     │
╰─────────────────────────────────────╯

おわりに

以上、Vibe Codingで共和暦の時計を実装してみた記事でした。

正直私は「コードが書きたいから書く」タイプのプログラマなのでVibe Codingを敬遠していたのですが、簡単なツールであればほぼ丸投げができることが分かりました。そして、ニッチな題材であっても設計に詰まることは無かったので、新しいアイデアに対しても使えそうです。

あとは自分でやりたい欲求を以下に抑えるかですね...

  1. 10時の位置(※グレゴリオ暦でいう12時の位置)です。

  2. 逆に、他の言語を使用する場合はコンテナ内にインストールする or サンドボックスボックスをベースイメージにした独自のイメージ定義が必要です。

  3. 初回に setTimeout で描画する瞬間を共和暦秒が変わる瞬間に合わせれば直ると思います(サボり)。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?