HTML 福笑い

https://github.com/miuchi-net

Next.js

TypeScript

Python

Docker

Rust

マルチで楽しめる福笑いです! HTML/CSSの腕を競おう!

Mutsuha Asada

na

abap34

推しアイデア

ローカルで昔ながらの遊びと、モダンな Web が組み合わさっていること。

作った背景

みんなであつまったときの盛り上がりになってほしかった。

推し技術

機械学習を色々なところで使ってユーザ体験を向上させたこと。

プロジェクト詳細

HTML 福笑い

HTML 福笑いは、リアルタイムにレンダされない ─つまり、目かくし状態でスタイルを記述してどれだけ目標に近づけられるかを競うゲームです!

ゲーム性としては、観戦やリザルトなどのシステムなどによって多くの人と盛り上がれる点、技術的にはモダンな言語・フレームワークによる堅牢なシステムと随所で機械学習を使ったゲーム体験の向上の工夫が推しポイントです。

ゲームの流れ

お題作成画面です。 お題とともに部屋を作成することができます。

image

参加者は部屋を選んで参加できます。

image

するとエディタ画面に遷移し、参加者はお題を目指して HTML とCSS を描くことになります。

image

全体の構成

フロントエンドは Next.js, バックエンドは Rust, HTMLのレンダや類似度の計算を行うサーバは FastAPI で実装されています。

技術的なトピック

1. 機械学習を使った類似度の計算

概要

ゲームが終了したあと、プレイヤーとしてはどのような経過でこんな惨状になったかが気になるところです。

そこでゲーム終了後のリザルト画面を作ることにしましたが、そこでヒントにしたのがボートゲームの形勢グラフです。

rendered image

ボートゲーム (例えば将棋) では、あとからその手によってどの程度評価値が変動したかを評価することができ、これの推移を見ることでゲームの流れを明確に振り返って楽しむことができます。

HTML 福笑いでも同様に、お題との類似度を評価して、その推移を描画する機能を実装しました 🙌

技術的説明

技術的には、類似度の計算は工夫の余地があるタスクです。

もっとも素直なのは二つの画像のピクセルごとの値の差の平均を取ることなどですが、これだと例えば「全く同じ図形だけど、左右反転している」という状況では、かなり異なった画像と評価されてしまいます。(ですが、明らかにこの二つの画像はそっくりです)

そこでこのアプリでは機械学習を使って人間の直感に近い「類似度」を計算することにしました。

より具体的には、ImageNet で事前学習した適当なモデルにそれぞれの画像を入力し、Conv層の出力のコサイン類似度によって類似度を定義しました。

(ものすごくざっくりいうと、大量の画像を食べたことによって「画像の特徴」っぽいものを出力できるようになった AI の二つの出力がどれくらい似ているかを調べました)

2. カラーパレットの生成

概要

目標に近づけるにはもちろん色を合わせないといけませんが、これをノーヒントでやるのは大変です。そこでカラーパレットを用意して、画面に表示しておくことにしました。

技術的説明

事前に適当に並べたカラーパレットをおいても良いですが、例えば赤色基調のロゴでは他の色がたくさんあっても仕方がないです。

そこで、画像から代表的な色を自動で選ぶアルゴリズムを実装することにしました。

具体的には、K-Means法を使いました。事前に設定したクラスタ内平方和を下回るまでクラスタリングを繰り返してそのときの各クラスタ中心を代表色として選んでカラーパレットとすることにしました。

(ものすごくざっくりいうと、出てくる色すべてと「それなりに近い色」を設定より近さの平均が小さくなるまで選ぶ、という方法でパレットを作りました。)

3. OpenAPIを利用したスキーマの記述

概要

openapi-generatorでコードを自動生成することによって開発を効率化しました!💪

技術的説明

多くのエンドポイントではHTTPメソッド、リクエストボディ、レスポンスの構造によってビジネスロジック以外の実装が定まります。これらの情報を OpenAPI に従ったスキーマとして記述することで、openapi-generatorによって多くのコードを自動生成しました。 これにより、ルーティングをはじめとした自明な部分は省略し、本質的な実装に注力できました。また、ドキュメントと実装が常に一致するのもメリットで、APIドキュメントはGitHub Actionsを利用して自動生成しています。(https://miuchi-net.github.io/hukuwarai-server)

これはサーバ側とクライアント側のやり取りをスムーズにするために役立ちました。

4. HTML のリアルタイムレンダリング

概要

フロント側でレンダを行うと、パフォーマンスと偽装の懸念があります。

そのため、バックエンド側のレンダ用サーバで高速に画像化しています。

技術的説明

画像化には puppeteer を用いています。 リクエスト毎にいちいちブラウザを立ち上げて画像化していると、観戦画面でのリアルタイム描画に耐える速度で動作させるのが難しいので、適切に再利用して並列に捌くことで十分高速に動作させています。

rendered image

Mutsuha Asada

@momeemt