7
5

AIで自分だけのバッジを集めよう!子供と一緒に楽しめる「Happy Badge」

Posted at

はじめに

突然ですが、「ヘイ!ダギー」をご存じでしょうか。
Disney制作の知育アニメなのですが、子供がどハマりするついでに私もハマっています。
非常にコミカルでポップ、軽快な音楽とストーリーで飽きずに観ていられます。

※公式サイトより抜粋
犬のダギーのチビッコ園に、個性豊かでゆかいな子どもたちが大集合!
~中略~
みんな、優しく見守っていてくれるダギーが大好き! 一日の終わりには、頑張ったごほうびとしてダギーからバッジがもらえるんだ。

「 頑張ったごほうびとしてダギーからバッジがもらえるんだ。」

ということで、楽しくチャレンジをしていろんなバッジを集めることができるアプリを作ってみました。(Googleアカウントですぐに始められます!)

Happy Badge

mockup.png

※PWAに対応していますので、「ホーム画面に追加」するとアプリのように利用できおススメです。

ホーム画面への追加方法

できること

コレクション

チャレンジに成功したらバッジをもらえて、コレクションとしてみることができます。
初期登録時には5枚のバッジが用意されており、それぞれにチャレンジの内容が設定されています。

image.png

つくる

自分でバッジを作ることもできます。
バッジの名前と「できた!」の条件を設定し、バッジのアイコンを決めます。
アイコンはプリセットが300種類以上あり、画像をアップロードしてはめ込むこともできます。
また、バッジの名前と条件からAIに生成してもらうことも可能です。

image.png

できた!

チャレンジに成功した(と判断した)ら、「できた!」から認定します。
表示されるバッジをタップしてコレクションに加えましょう。

image.png

どんどんチャレンジ

次にチャレンジしてみるバッジを一緒に選んであげましょう。(いつでも変更可能です。)

image.png

「あれ?おかたづけバッジ持ってたんじゃなかったっけ??」は2、3回効果があります。ぜひお試しあれ。

技術まわりの話

フレームワーク

Reflex

PythonだけでWebアプリが作れる系のフレームワークです。
裏ではNext.js+FastAPIの構成に変換されています。

UIデザインにはChakra-UI、Radix-UI、Tailwind CSSが採用されており、通常のCSSパラメータも指定可能です。

また、npmで公開されている任意のReactコンポーネントを取り込むことができるのも便利です。(今回も全画面のローダーなどを利用しています。)

※こんな感じで使えます(上記リンク先より抜粋)

class ColorPicker(rx.Component):
    library = "react-colorful"
    tag = "HexColorPicker"
    color: rx.Var[str]
    on_change: rx.EventHandler[lambda color: [color]]


color_picker = ColorPicker.create


class ColorPickerState(rx.State):
    color: str = "#db114b"


def index():
    return rx.box(
        rx.vstack(
            rx.heading(
                ColorPickerState.color, color="white"
            ),
            color_picker(
                on_change=ColorPickerState.set_color
            ),
        ),
        background_color=ColorPickerState.color,
        padding="5em",
        border_radius="1em",
    )

image.png

データベース

Supabase

いわゆる BaaS (Backend As A Service) ですが、今回は純粋にRDBMSのみを利用しています。WebUIが抜群に使いやすいです。

※ReflexではDB情報を設定することでalembicを使ったマイグレーションや、ORMとしてSQLAlchemyが利用可能です。
以下の記事がわかりやすいです。

認証・認可

Google OAuth 2.0

個人情報はできる限り自前で保存したくないのでみんな大好きGoogle先生に頼ります。

決済

Stripe

こちらも個人情報を保存したくない&決済系は自前で実装するのが怖いので、全面的に頼っています。
PaymentLinks→Hooksを使ってAWS LambdaをキックしてSupabaseのクレジット履歴を編集しています。

画像生成

OpenAI API Image generation(DALL·E2)

バッジ作成の機能で利用しています。
今回はInpaintingが必要だったのでDALL·E3ではなくDALL·E2です。
StableDiffusionなども試したのですが、マスク画像やパラメータの調整が下手だったのかいい感じのイラストが生成されず。。
一番それっぽく生成してくれたOpenAIを選定しました。

以下のようにマスク画像を用意して渡してあげると機能します。(返ってくる画像データは透過がなくなってしまっているので、ついでに背景を透過しています。)

base mask alpha
preset_base.png preset_base_mask.png preset_base_alpha_mask.png
def inpaint(title):

    prompt = f"""
    Cute and pop clipart for kids.
    Generating theme: {title}
    """

    image = Image.open("base.png").convert("RGBA")
    mask = Image.open("base_mask.png").convert("L")

    buffered = io.BytesIO()
    image.save(buffered, format="PNG")
    image_bytes = buffered.getvalue()

    buffered.seek(0)
    mask.save(buffered, format="PNG")
    mask_bytes = buffered.getvalue()

    response = openai.images.edit(
        model="dall-e-2",
        image=image_bytes,
        mask=mask_bytes,
        prompt=prompt,
        n=1,
        size="512x512",
    )

    response = requests.get(response.data[0].url)

    # 背景を透過
    gen_image = Image.open(io.BytesIO(response.content)).convert("RGBA")
    mask = Image.open("alpha.png").convert("L")

    gen_image.putalpha(mask)

    return gen_image

ややアメリカナイズされている感は否めませんが↓のように生成されます。
image.png

ホスティング

Reflex Hosting Service

Reflexが公式でサポートしているホスティングサービスです。

CLIからの操作になりますが、reflex initでプロジェクトを作っていれば、reflex deployだけで完了できます。(環境変数の設定など若干めんどくさいですが、shellを作っておけばそこまで面倒ではないかなという印象です。VercelやFly.ioのようにリッチなWebUIはないので好みがわかれるかも。)

※Next.jsとFastAPIとしてビルドされるので、それぞれコンテナに詰めてデプロイすればどこでもホスティングはできるようです。

おわりに

Reflexの練習がてら子供と一緒に楽しめるWebアプリを作ってみました。
Reflex自体ちょくちょく触ってはいたものの、構想からリリース、記事公開まで2時間/日×3週間ほどでできたので本当に使いやすいフレームワークだと思います。
これからもっと広まって欲しい!

※Discord内には日本語チャンネルもありますので是非。

7
5
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
7
5