【ChatGPTと作る】あしのさきの動物パンプリン占い【クソアプリ】

クソアプリ歴3年目のゆきです。一昨年はデスクトップでお寿司:sushi:を回し、去年は世の動くサイトを粉砕:rage:しました。

https://qiita.com/yuneco/items/1fa72413ab011d1c0ac5

https://qiita.com/yuneco/items/24a209cb14661b8a7a20

今年も…って思ったけど、毎回自分でハードル上げ過ぎてしんどくなるので、**今年は全部AIに任せて**みようと思います:relaxed:

## こちらが完成した「あしのさきの動物パンプリン占い」です

アプリ： https://yuneco.github.io/animal-panpudding/ 
※ スマホでも動きます
リポジトリ： https://github.com/yuneco/animal-panpudding

![pp1214.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245740/f0b32158-8fb7-9de1-17a5-038eda27f807.gif)

## これは一体何？？

>🤖 「あしのさきの動物パンプリン占い」は**クソアプリの究極**の仕上がり！ **脚の先の写真**から**天気を推定**し、**おすすめの動物パンプリンと占い**をお届けします。 **無駄**に面白くて、**もっともっと意味不明**な占いが楽しめるかも？ お試しあれ！

アンダスタン？ では始めましょう

## ChatGPTとアイデアを練る

※ 以後🤖 = [ChatGPT](https://chat.openai.com/chat)です。読みやすくするため一部修正・削除等調整しています。強調は全て筆者です。

🐱 何の役にも立たないクソアプリの良いアイデアを10個考えてください。できるだけ脈略がなく、突拍子もないアイデアを求めます。ただし、良いクソアプリは複雑な記録・計測・分析・集計を行ってはいけません。

>🤖
「**おしゃべりクジラ**」- クジラの音声を再生しておしゃべりさせるアプリ。
「**私の口臭計**」- 口臭を計測して、どの程度まで改善すればいいかを教えてくれるアプリ。
「**胸がときめく目の診断**」- 目の真ん中をタップするだけで、胸がときめくかどうかを診断するアプリ。
「**天気色**」- 天気を色で表示するアプリ。
「**脚の先の天気**」- 脚の先をカメラで撮影して、天気を判定するアプリ。
「**おうちでパンプリン**」- 自宅で作るパンプリンのレシピを紹介するアプリ。
「**夢占いマスター**」- 夢を記録して、その夢を占い師が解説するアプリ。
「**気分を変える音楽**」- 気分を診断して、その気分に合った音楽を提案するアプリ。
「**星座の自己満足**」- 星座ごとに自己満足する方法を教えてくれるアプリ。
「**猫の声で起きる**」- 猫の声で起きるアラームアプリ。


無限にネタ出ししてくれるので最高ですね。ただ、クソアプリなのに有用なアイデアや難易度高そうなネタも多いです。良さげな物をもう少し掘ってみます。

🐱 「脚の先の天気」についてもう少し教えてください。どのようなアプリですか？また、どのあたりがクソアプリとして高評価だと考えますか？

>🤖
「脚の先の天気」は、脚の先をカメラで撮影して、その映像から天気を判定するアプリです。例えば、晴れの日は青空が映っていると判定され、雨の日は雨が降っている様子が映っていると判定されます。
このアプリは、天気予報サイトやアプリでも簡単に確認できる天気情報を、カメラで脚の先を撮影することで取得するという、**非常に脈絡がない**アプリと言えます。また、天気を判定するためには、**脚の先を撮影しても意味のない情報しか得られない**ため、このアプリの判定精度は低くなると思われます。
そのため、「脚の先の天気」は、**無駄な操作をしなければならない**という点や、低い判定精度が指摘される可能性があり、クソアプリとして高評価されると考えられます。


🐱 「おうちでパンプリン」についても教えてください。パンプリンとはどのようなものでしょうか？また、お家でつくれるレシピを紹介するアプリは役に立ち、脈略もありそうに見えますが、どのあたりがクソアプリとして高評価だと考えますか？

>🤖
「おうちでパンプリン」は、家庭で作るパンプリンのレシピを紹介するアプリです。パンプリンとは、英語で「pumpkin」と呼ばれる、**カボチャを使ったスイーツ**のことです。「おうちでパンプリン」は、家庭で手軽に作れるパンプリンのレシピを紹介してくれるアプリです。お家でスイーツを作るのは楽しいものですが、レシピを探すのは大変です。このアプリは、そのような問題を解決してくれると考えられます。
しかし、このアプリは、料理レシピが豊富な料理アプリや食育アプリなど、多くの料理アプリがすでに市場に存在するため、**特に新しいものを提供しているとは言えません**。また、家庭で作るスイーツを紹介するアプリとしては、かなり特殊なものと言えるため、**需要が少なく、利用する人が限られる**と考えられます。そのため、「おうちでパンプリン」は、特殊なテーマのアプリであり、需要が少ないと指摘される可能性があり、クソアプリとして高評価されると考えられます。


こいつ...強いぞ...
ただどうやら「尖り過ぎてニッチなほどクソアプリ」だと考える傾向が出てきちゃったようです。これでは**クソアプリの真髄には程遠い**と言わざるを得ません。こんな時は掛け算してアイデアを膨らませましょう。

🐱 需要が少ないだけではクソアプリとしては不十分です。「脚の先の天気」と「おうちでパンプリン」を組み合わせて、もっと意味不明なクソアプリのアイデアを作れますか？

> 🤖
「脚の先の天気」と「おうちでパンプリン」を組み合わせたクソアプリのアイデアとして、以下のようなものが考えられます。
「**脚の先のパンプリン天気**」- 脚の先をカメラで撮影して、その映像から天気を判定し、その天気に合ったパンプリンのレシピを紹介するアプリ。
「**脚の先のパンプリン地図**」- 脚の先をカメラで撮影して、その映像から天気を判定し、その天気に合ったパンプリンを作るお店や飲食店の地図を紹介するアプリ。
「**脚の先のパンプリン占い**」- 脚の先をカメラで撮影して、その映像から天気を判定し、その天気に合ったパンプリンの占いをするアプリ。

>これらのようなアプリは、「脚の先の天気」と「おうちでパンプリン」を組み合わせたものであり、**そのアプリ自体が非常に無駄である**と言えます。また、**脚の先をカメラで撮影することで得られる情報は、天気やパンプリンには関係のないものである**ため、このアプリの判定精度も低くなると考えられます。
そのため、「脚の先のパンプリン天気」や「脚の先のパンプリン地図」など、「脚の先の天気」と「おうちでパンプリン」を組み合わせたアプリは、**脈絡がない内容や低い判定精度**が指摘される可能性があり、**クソアプリとして高評価**されると考えられます。

🤖 「**そのアプリ自体が非常に無駄である**」

いいですね。:tada:**最高の褒め言葉**:tada:です。
今回は「脚の先のパンプリン占い」にかわいい動物の要素を足した「あしのさきの動物パンプリン占い」を作りましょう。選定理由は一番意味不明でありながらそこはかとなくおしゃれみと可愛さが感じられたから。実用性が皆無なのも良いですね。

## ChatGPTとコードを書く

🐱 クソアプリで判定した天気や気温からおすすめのパンプリンを紹介するにはどのような技術やアルゴリズムを用いると良いでしょうか？良いクソアプリの条件として、データベースは利用したくありません。また、クソアプリなので精度は低くても問題ありません。

>🤖 そのような条件で、おすすめのパンプリンを紹介するには、簡単な条件分岐や乱数生成の機能を持ったプログラミング言語を用いて、天気や気温を判定した結果に応じたおすすめのパンプリンを紹介するプログラムを作成することができます。例えば、JavaScriptを用いて以下のようなプログラムを作成することができます。

```js
// 判定した天気を入力する変数
let weather = "晴れ";
// 判定した気温を入力する変数
let temperature = 10;

// 天気からおすすめのパンプリンを紹介する
if (weather === "晴れ") {
  // 晴れの日には「晴れのお日様パンプリン」がおすすめ
  console.log("晴れの日には「晴れのお日様パンプリン」がおすすめです");
} else if (weather === "曇り") {
  // 曇りの日には「曇り空のロマンティックパンプリン」がおすす
```

いきなりコード書いてきた...だと？
アプローチを聞いただけでコードが出てくるとはなかなか仕事ができるヤツです。でもちょっとイケてないですね:information_desk_person:

🐱 if文を多用するのはスマートではないので、先に天気に対応したパンプリンの連想配列と気温に対応した動物の名前の連想配列を作成し、その2つを使って天気と気温に合わせたおすすめの動物パンプリンを表示するように修正してください

```js: 🤖 JavaScriptを用いたプログラム例を示します。
// 天気からおすすめのパンプリンを定義する連想配列
let weatherPancake = {
  "晴れ": "晴れのお日様キツネパンプリン",
  "曇り": "曇り空のロマンティックフクロウパンプリン",
  "雨": "雨の日のロマンティックパンプリン"
}

// 気温からおすすめの動物を定義する連想配列
let temperatureAnimal = {
  0: "ホッキョクグマ",
  2: "マカク",
  4: "フクロウ",
  （長いので中略）
  26: "メジロ",
  28: "イノシシ",
  30: "トラ"
}

// 判定した天気を入力する変数
let weather = "晴れ";
// 判定した気温を入力する変数
let temperature = 10;

// 天気からおすすめのパンプリンを紹介する
console.log(weatherPancake[weather] + "がおすすめです。");

// 気温からおすすめの動物を紹介する
console.log(temperatureAnimal[temperature] + "の形をしたパンプリンがおすすめです。");
```

出力が2文に分かれているのはいまいちですね

🐱 `weatherPancake`から動物の名前を削除し、`temperatureAnimal`と組みあわせて、天気と気温に合わせたおすすめ動物パンプリンひとつだけを表示するように修正してください

```js:🤖 JavaScriptを用いたプログラム例を示します。
// 天気からおすすめのパンプリンを定義する連想配列
let weatherPancake = {
  "晴れ": "晴れのお日様",
  "曇り": "曇り空のロマンティック",
  "雨": "雨の日のロマンティック"
}

// 気温からおすすめの動物を定義する連想配列
let temperatureAnimal = {
  0: "ホッキョクグマ",
  2: "マカク",
  4: "フクロウ",
  （略）
  26: "メジロ",
  28: "イノシシ",
  30: "トラ"
}

// 判定した天気を入力する変数
let weather = "晴れ";
// 判定した気温を入力する変数
let temperature = 10;
// 天気と気温からおすすめの動物パンプリンを紹介する
console.log(weatherPancake[weather] + "の" + temperatureAnimal[temperature] + "パンプリンがおすすめです。");
```

🐱気温に対応する動物は0度から30度までの5度区切りに変更し、入力された`temperature`に最も近いものを返すように修正してください
🐱入力された気温が0度未満または30度を超える場合でも正しく動作するよう、気温を0度から30度の範囲に丸めてから5の倍数に丸めるように修正してください
🐱再代入しない変数は`const`で定義してください
🐱TypeScriptで書き直せますか？
🐱天気はユニオン型で書き、その型を使って`weatherPancake`を定義してください

↓ここまでやった最終形

```ts:🤖 TypeScriptを用いたプログラム例を示します。
// 天気を定義するユニオン型
type Weather = "晴れ" | "曇り" | "雨";

// 天気からおすすめのパンプリンを定義する連想配列
const weatherPancake: { [key in Weather]: string } = {
  "晴れ": "晴れのお日様",
  "曇り": "曇り空のロマンティック",
  "雨": "雨の日のロマンティック"
}

// 気温からおすすめの動物を定義する連想配列
const temperatureAnimal: { [key: number]: string } = {
  0: "ホッキョクグマ",
  5: "マカク",
  10: "フクロウ",
  15: "シマウマ",
  20: "ラッコ",
  25: "クマ",
  30: "キツネ"
}

// 判定した天気と気温からおすすめの動物パンプリンを紹介する関数
function recommendPancake(weather: Weather, temperature: number): string {
  // 入力された気温を0度から30度の範囲に丸める
  let roundedTemperature = Math.min(Math.max(temperature, 0), 30);
  // 気温を5の倍数に丸める
  roundedTemperature = Math.round(roundedTemperature / 5) * 5;
  // 気温からおすすめの動物を返す
  return weatherPancake[weather] + "の" + temperatureAnimal[roundedTemperature] + "パンプリンがおすすめです。";
}
```

よくない書き方やロジックのミスを手取り足取り指摘していけはそれなりに形になるのは凄いですね。**「ユニオン型にしてくれ」で話が通じた**のはちょっとびっくりです。

## 脚の先の写真から天気を推定する

🐱 脚の先の写真から今日の天気を推定するにはどうしたら良いでしょう？クソアプリなので複雑なプログラムは書きたくありません

>🤖 **特徴量を抽出する必要はありません**。一定の確率で天気を**ランダムに決定することで、十分にクソアプリ感を出す**ことができます。例えば、Math.random()を使って0から1までのランダムな数値を生成し、その範囲を3つの状態（晴れ、曇り、雨）に分割します。そして、生成されたランダムな数値がどの範囲に属しているかで天気を決定します。また、必要に応じてランダムに変更する**確率を調整することで、よりクソアプリらしい判定を実現する**ことができます。

こいつ...できるぞ

🐱 実にクソで良いアイデアですが、さすがにもう少しまともな判定を行いたいです

>🤖 その場合は、事前に**天気を手動で入力する**か、**天気予報サイトやアプリから取得して判定する**ことができます。また、現在の季節や地域によって晴れや曇りの出現確率が異なるため、それらも考慮した判定アルゴリズムを作成することでより正確な判定ができるでしょう。

チートwwww

さすがに良心が咎めたので、天気の推定にはGoogleの[Teachable Machine](https://teachablemachine.withgoogle.com/train/image)を使ってモデルを作ることにします。学習素材にはスマホのアルバムから天気がわかる脚の先の写真を100枚くらいピックアップ…できるはずもないので、適当なCCライセンスの写真素材から雰囲気で10枚くらい選んで突っ込みます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245740/8b8b0336-c6f9-5b2a-69b7-42179a5c2df2.png)


作ったモデルはダウンロードして[@teachablemachine/image](https://www.npmjs.com/package/@teachablemachine/image)と[@tensorflow/tfjs](https://www.npmjs.com/package/@tensorflow/tfjs)に読ませれば数行のコードで推定を行なって結果を返してくれます。はじめて使ったけど簡単で良いですね:open_hands:

```ts
import * as tmImage from '@teachablemachine/image'
import { WEATHER_NAMES } from './weather'

let modelLoader: ReturnType<typeof tmImage.load> | undefined = undefined

/**
 * 学習済みの分類器モデルをロードする
 * @returns モデルを返すPromise
 */
const loadModel = () => {
  if (!modelLoader) {
    // 初回のみロードして、2度目以降はPromiseを返す
    modelLoader = tmImage.load('./ml/model.json', './ml/metadata.json')
  }
  return modelLoader
}

/**
 * 足元の画像から天気を推定して返します
 * @param imageElement 足元の画像
 * @returns 判定結果の天気
 */
export const detectWeather = async (imageElement: HTMLImageElement) => {
  const model = await loadModel()
  const result = await model.predict(imageElement)
  // probabilityの最も高いものを正解とする
  result.sort((a, b) => b.probability - a.probability)
  const { className, probability } = result[0]
  const weather = WEATHER_NAMES.find((w) => w === className)
  if (!weather) return undefined
  // 天気と確率を返す
  return { weather, probability }
}
```

## 占いのメッセージを量産する

メッセージデータって作るの面倒ですよね。きっと近い将来ChatGPTレベルのAIが端末のローカルでサクサク動くようになるんでしょうけど、今はまだきついので、事前にたくさんメッセージのテンプレを作っておくことにします。

🐱 晴れの天気におすすめの動物パンプリンの名前と占いのメッセージのペアを3つ作り、JavaScriptのコードとして出力してください。ただし動物の名前は変更できるよう変数にしてください

```js:🤖 JavaScriptのプログラム例を示します。
// 動物の名前
const animal: string = "ホッキョクグマ";

// 晴れの天気におすすめの動物パンプリンの名前と占いのメッセージのペア
const weatherPancake: { [key: string]: string } = {
  "お日様のパンプリン": "今日は最高な日になります！",
  "真夏の太陽パンプリン": "暑い日が続くかもしれませんが、元気に乗り切りましょう！",
  "晴天の霹靂パンプリン": "偶然を狙っていきましょう！運が良ければ何かが起こるかもしれません。"
};

// 晴れの天気におすすめの動物パンプリンを表示する
for (const [pancake, message] of Object.entries(weatherPancake)) {
  console.log(`${animal}の${pancake}：${message}`);
}
```

🐱 占いメッセージにも動物の名前を入れることができますか？

```js:🤖 占いメッセージにも動物の名前を入れることができます。JavaScriptのプログラム例を示します。
// 動物の名前
const animal: string = "ホッキョクグマ";

// 晴れの天気におすすめの動物パンプリンの名前と占いのメッセージのペア
const weatherPancake: { [key: string]: string } = {
  "お日様のパンプリン": `${animal}たちがいつも幸せそうです！`,
  "真夏の太陽パンプリン": `${animal}たちは暑さを乗り切るためにたくさん水を飲んでいます！`,
  "晴天の霹靂パンプリン": `${animal}たちは今日も晴れた空を見上げています！`
};
```

🐱 占いのメッセージは運勢や今日の行動のアドバイスを含めるべきです。動物の名前を含めつつ、占いのメッセージとしてもっと適切な例に修正してください

```js: 🤖 動物の名前を含めつつ、占いのメッセージとしてもっと適切な例をJavaScriptのプログラム例として示します。
// 動物の名前
const animal: string = "ホッキョクグマ";

// 晴れの天気におすすめの動物パンプリンの名前と占いのメッセージのペア
const weatherPancake: { [key: string]: string } = {
  "お日様のパンプリン": `今日はとても運が良さそう！${animal}たちがいるからかもしれませんね！`,
  "真夏の太陽パンプリン": `暑さに負けず、快適に過ごすためのヒントを${animal}たちがお届けします！`,
  "晴天の霹靂パンプリン": `今日は晴れた空を見上げて、新しい出会いやチャンスを探してみましょう！${animal}たちはきっと応援してくれます！`
};
```

最高ですね
ここまで来ればあとは量産するだけです。

## アプリUIとデザインの実装

ついでにデザインもやってもらおうかと思ったのですが、残念なことにChatGPTが高負荷でダウンしてしまったので、ここから先は全て手組みです。サクッとVueで作ります。ここら辺はそんなに面白くないので気になる方はリポジトリ覗いてください。

## 感想： AIの作るクソアプリは本物（褒めてない）

というわけで、「ChatGPTと作るクソアプリ」お楽しみいただけましたでしょうか？

私は...**:upside_down:正直結構辛かったです:upside_down:**
出来上がりは確かに**最高レベルのクソ**アプリなんだけど...なんていうか...辛い

結局のところ、我々**クソアプリ作家は自分の考えたクソアプリを愛して**いるのです:heart_eyes_cat:
愛のないクソアプリ開発は辛い:crying_cat_face:

「ChatGPTと作るクソアプリ」はというと...これ、あれだ
社内イベントとかのハッカソンで大して課題意識とかないけどネタだけでサービスをひねくり出して、1日目の終わりはそれなりに全員テンション高く帰宅したものの2日目の朝冷静に考えみたら「今日1日これ実装して発表までするのか...」ってやめたくなるあの気持ちに似てる

とはいえ、**ブレストのお供やデータの量産、プレゼン用の理論武装などなど...わりと真面目に使える子なのも事実**です。来年どうなっているのか、楽しみ＆怖いですね

## おまけ： パンプリンの作り方

🐱「晴れのお日様パンプリン」の材料と作り方を簡単に説明してください

>🤖「晴れのお日様パンプリン」は、晴れた日にぴったりのパンプリンです。以下の材料と作り方で作ることができます。
```
材料:
- カボチャ (1個)
- 砂糖 (大さじ1)
- 塩 (小さじ1/4)
- 卵 (1個)
- 薄力粉 (大さじ2)
- 小麦粉 (大さじ1)
- お好みの生クリーム

作り方:
- カボチャを切り、皮をむいて中を砂糖と塩を入れて混ぜる。
- 卵を加えて混ぜる。
- 薄力粉と小麦粉を加えて混ぜる。
- 型に流し入れ、180度のオーブンで30分焼く。
- 焼けたら、生クリームをトッピングして完成です。
```

>🤖 「晴れのお日様パンプリン」は、晴れた日に作ることで、さわやかな気分になれると思われます。

🐱 ほぼほぼカボチャですね 🎃

明日は @mizuhugu35 さんです！