ブラキオカップ

Eatit(イーティット)

https://github.com/k1tikurisu/internet-avengers

TypeScript

React

Figma

Python

Docker

草食恐竜をGitHubの草で育てよう!

Daiki Maekawa

Ryo Kameoka

Keigo Okamoto

推しアイデア

GitHubのコミットをエサとして恐竜が4段階進化する!コミットの質によってエサの質も変わる!他の人が育てた恐竜にエサをあげれたり・・?何日かコミットしなかったら恐竜は死んでしまうよ。(エンジニアの皆さんなら数日コミットしないことなんてないですよね)

作った背景

既存のGitHubのスコアリングは、IssueやREADMEの更新、BOTのコミットなどでハックできることが多く、数値は参考程度になることが多いです。 「コミットの質までみてスコアリングしたい」 「コミットするたび、かわいいものをみて癒されたい」 そんな思いから作りました。

推し技術

抽象構文木ベースの差分解析によりコミットをスコアリングしてエサの質を決定します。また、ユーザのコミット傾向も保持しており、ユーザごとに成長速度が異なります。素材は全て自作しており、コード品質やアニメーションにもこだわっています。

プロジェクト詳細

システム構成図

フロントエンドはPlasmo、バックエンドはFastAPI、サーバーはRenderです。RenderにDockerベースでデプロイし、GASでサーバーが落ちたら通知されるようにしています。GASはClaspというライブラリを使用し、GitHub Actionsで自動デプロイしています。

image

推し技術

バックエンド

DockerコンテナベースでFastAPIと、差分解析器であるGumTreeと多言語対応するための変換器であるTree-shitterの実行環境を構築しています。コミット情報からコード差分を評価し、エサの質を算出しています。また,ユーザのコミット傾向もDBに保存しているため,ユーザによって成長速度が異なります。

ディレクトリ構造

api ├── client # GitHub APIを叩く ├── config # GitHub APIを利用するためのconfig ├── cruds # DBのORM操作 ├── database.py ├── db.sqlite3 ├── libs # GumTreeの結果に対する重みの計算 ├── main.py # エントリーポイント ├── migrate_db.py # DBのマイグレーションスクリプト ├── models # DBのテーブル,カラム名定義 ├── routers # パスオペレーション関数を定義 ├── schemas # スキーマ定義 ├── stats # コミットのスコア計算 └── utils # utility関数

エサの質の計算ロジック

GumTreeとTree-sitterによって現在主要な16言語の差分解析に対応しています。GumTreeは、コード差分から、追加、削除、移動、更新操作をトークン単位で検出できるため、正確な質の評価が可能です。非対応の言語についても、質を評価するロジックを用意しています。

  • 共通処理
    • GitHubAPIから取得できる、言語の種類、追加行数、削除行数、変更ファイル数を基に該当コミットのスコアを算出する
    • 例えば、設定ファイルの変更や行の削除ばかりの変更だとほとんど成長しないようになっている
  • 解析可能な16種類いずれかの変更差分の場合
    • GumTreeを利用した抽象構文木ベースの差分解析により、ノードの追加、削除、移動、更新を検出し、移動の操作が全体の50%を占める場合と更新操作のみが80%を占める場合はリファクタリングとみなし重みを軽くする
    • ノードまたはツリーの追加が削除の数を上回っている場合は重みを増やし、逆の場合は重みを変更せずデフォルトの経験値のままとする

フロントエンド

Plasmoというフレームワークを使用し、React × TypeScriptでChrome拡張機能を作成しました。Plasmoはまだv0系で発展途上のフレームワークのため、挑戦ポイントの1つです。

ディレクトリ構成

コンポーネントやロジックの依存関係の方向を意識したディレクトリ構成になっています。

frontend ├── assets # 恐竜の素材 ├── src │   └── contents # Contents Scriptを格納 │   ├── api # APIとの通信部分 │   ├── components # コンポーネント │   │   ├── container │ │   │   ├── container.module.css # CSS Modules │   │   │   ├── container.test.tsx # Unit Test │   │   │   ├── container.tsx # JSX │   │   │   └── index.ts │   │   └── dino-home │   │      ├── components # dino-homeだけで使うコンポーネント │   │      └── index.ts │   ├── index.tsx # 親コンポーネント │ └── utils # utility関数 │   ├── get-user-name.ts │   ├── get-user-name.test.ts ... ├── tests # testのセットアップ、utilityなど ├── tsconfig.json └── yarn.lock

こだわりポイント

  • 素材
    • 恐竜の素材はデザインツールで全て自作しています。 image
  • アニメーション
    • JavaScriptでstyleを保持すると不安定なアニメーションになりやすいため、全てCSS Animationに寄せることで安定したアニメーションを実現しています。
  • 品質保証
    • テスト:単体テストで各コンポーネント・ロジックの動作を保証しています。
    • リント:Biomeを使用してコードのスタイルを統一しています。
  • 開発環境
    • モックサーバーをフロント側で用意し、バックエンドと非同期で開発できるようにしています。
  • 非同期処理
    • バックエンドの計算処理に時間がかかるため、計算結果を待たずにアニメーションを流すことで、一生ご飯を食べ続けることを防ぐ
  • 隠し要素
    • 現在の成長度合いを経験値として見れる機能
    • 他の登録ユーザのエサをかってにあげる機能

その他

  • コンテナの軽量化
    • GumTree公式が提供しているDockerイメージはビルドできなかったので、バージョン固定など含めてイメージを自作した
    • Tree-sitterのパーサが重すぎてコンテナ上にクローンできない
      • ハッシュを指定してzipダウンロードすることで、高速かつ軽量にコンテナ内に環境構築
      • マルチステージビルドを使って、GumTreeのビルドステップを分け、ビルドファイルだけをコンテナ内にコピー
  • 死活監視
    • GASでプロダクト環境に定期アクセスすることで、スリープ防止とサーバーが落ちてたら通知されるように
  • 開発環境
    • フロントエンドはNode.js、バックエンドはDevContainerを使ってコンテナ上で作業できるようにしています
      • バックエンドはGumTreeとTree-sitterを動かすためにJava、Node.js、C、Pythonの実行環境が必要になるため
  • Plasmo便利/大変な面も
    • 同じ境遇のIssueがほとんどない
    • パス解決周りで、単体テストの環境構築大変だった
      • 本当はStorybook/Playwright使ってちゃんと書きたかったけど時間足りず

Daiki Maekawa

@k1tikurisu