はじめに
今年の11月2,3日には工大祭が開催されました。traPも traPalette という名前で出展していました。詳しくは↓の記事をお読みください。

今年の工大祭は爆破予告のおかげで色々かき回されてしまいました...
僕は今年の工大祭出展責任者の一人だったので、初日夜以降忙しかったなぁ
そんな予告犯への私怨はそれとして、工大祭の出展にはそこそこに作業が発生します。大まかにこんな感じです:
- JIZIとのやり取り
- スタッフの募集・管理
- レイアウト作成
- ポスター管理
- 物販管理
どれもそこそこに重いタスクではありますが、ポスター管理は特に厄介者です。他のタスクは最低限進捗の管理ができますが、ポスター管理は少し違います。張り出したポスターを回収する時、どこにポスターを貼ったかを正確に覚えている必要があり、忘れてしまうと回収漏れが発生してしまいます。またポスターは飛んで行ってしまうこともあるので、単に枚数で管理しても、足りない原因が回収漏れなのかポスターの消失なのかわかりません。
この記事では、そんなポスター管理のためのツールを作成したよ、ということについて書いていきます。
チャットBOTでの管理
事の始まりは工大祭準備日。ちゃんとポスター管理しないとなぁと思いながら部室でレンタルPCの到着を待っていました(このPCの納品書が入った箱が途中で配送止まっていて丸一日潰れたという話はまた今度)。こうしたツールを作るとき、最も手っ取り早い方法はDiscordBOTのようなチャットツールのBOTとして実装することです。通常ツールの作成は裏のロジックと表のUI作成が必要ですが、BOTはUI部分をすっ飛ばしてくれるからです。便利。
ところで、僕はtraQ(traPのチャットツール)にろぼるーくというBOTを作っていて、これに僕の発言の一部を記録してもらっています。

つまりろぼるーくの 機能として ポスター管理を実装すれば、初期の環境構築もすっ飛ばしてツールが作れてとても嬉しいわけです。
というわけでさくっと1時間で実装完了。CopilotのおかげでほぼTab連打みたいな開発だったものの、ここまで早くできるとは思っていませんでした。
機能
ろぼるーくのポスター管理機能は次の機能(コマンド)を備えています
- register [id]: 指定したIDで投稿を記録します。これに写真を付けておくとポスターを貼った場所がわかります。
- query [id]: 指定したIDで記録された投稿を引用して返信します。これで指定したIDのポスターの場所を調べることができます。
- collect [id]: 指定したIDのポスターを回収済みとして登録します
- remains: 未回収のポスターのID一覧を返信します。
あとは、ポスターの裏に数字を振ってID管理をすれば、このツールに乗っけることができるようになります。
このツールには一点、懸念点がありました。それはポスターの情報の保持がインメモリだったことです。ろぼるーくは家で動かしている Raspberry Pi 4B 上で動いています。つまり、ろぼるーくが何かしらのエラー(ネットワークエラーなど)で落ちたり、誤って電源コードをひっかけて抜いてしまったりしたらポスターの情報が全て消えてしまうんです。エラーハンドリングはしっかりしている(はず)なので、準備日から撤収までラズパイには絶対に触らないようにしていました。結局最終日までろぼるーくは落ちずに動いてくれました。感謝です。
使ってみる
準備日・撤収で使用した感じ、割としっかり使えました。残ってるポスターがどこにあるのかが一発でわかるのはとても助かります。
ところで、ろぼるーくはそもそもチャットBOTで、他の人の発言に反応して発言します。一応コマンドに対しては反応しないようにしていますが、連絡などをすると反応してしまうことがあります。運用中もちょいちょいしゃべっていました。(反応確率は5%なのに、僕のほぼすべての発言に反応してきました...なにがあった)

3日を通じてろぼるーくはしっかり仕事してくれました。ありがとう。

ちゃんと開発
ろぼるーくのポスター管理機能ですが、色々不便なところはありました。
- 登録などでコマンド名を打たないといけない
- ポスターが風で飛ばされたことを記録できない
- etc.
ということで、工大祭が終わってひと段落してからはポスター管理を効率的に行うためのWebアプリの開発に着手しました。
技術スタック
以下のような構成で組み立てました。僕がフルスタックで立てるときにいつも使うスタンダードな設定です。
バックエンド
- Go
- Echo
Goは良いですよね。シンプルな言語仕様で複雑な処理を書けます。エラーハンドリングが面倒とか、記述が冗長とか言われたりしますが、冗長こそ正義です。
フロントエンド
- Next.js (on typescript)
- tailwind css
traPのフロントエンドはVue.jsが主に使われるのですが、Next.js (React) のコンポーネントで記述する仕組みと、サーバーコンポーネントとクライアントコンポーネントの仕組みが大好きです。
成果物
こんなものができました。



回収処理がワンタップでできるようになったり、各ポスターの状態が一目でわかったりするのが特徴です。
作ってみて
まだWebのフルスタック開発の経験はなく、ドメイン駆動設計なるやり方とか、たまねぎアーキテクチャとかよくわかっていませんが、それでも技術として色々得るものがありました。開発をレイヤーで分け、各部分で行うべき処理・責任を分けることで、開発の見通しが良くなりました。データのバリデーションも、こうして分けると良く明確になるんだなと感じました。
追加機能:物販管理
ポスターを実装して、まだモチベーションがあったので、物販管理機能も実装することにしました。物販管理には次の機能があります
- 物品の登録
- 工大祭に販売するものの登録
- 会計処理
- 売り上げの管理
ポスターの余興のような感じで実装した物販管理ですが、ポスター管理よりも複雑な構造になってしまいました。複数のイベントで利用できるようにするため、物品そのものと販売物を分けたせいで実装がほぼ二倍になったのが原因です。とはいえちゃんと実装できてよかったです。
おわりに
今回は工大祭で使えるツールを作ったことを記事にしてみました。次の工大祭の前に一度どこかでテストしてみたいですね。これで未来永劫traPの工大祭タスクが軽くなってくれるとありがたいです。
明日は @SAH123 さんの記事です。楽しみ!
