ミニWEBサービス「おすすめごはん」を作りました。
5つの簡単な質問に回答するだけで、あなたにおすすめのごはんを提案するサービスです。
まずはやってみましょう。
https://an-248.github.io/suggest_dish/
コードはこちら。
https://github.com/AN-248/suggest_dish
作った動機
面白いものを作りながら技術力をアップしたいという思想のもと、
職場の複数のエンジニアで、アイデア出しをしたり、ごはんデータ入力したり、コードを書ける人が書いたり、数学できる人がアルゴリズムを考えたりして、ゆるーく完成しました。
使用技術
フロントエンドはvue3
バックエンドはありませんが、ごはんは全165品目のデータがあり、googleのスプレッドシートに登録しています。
Google App Script(GAS)を利用してスプレッドシートの情報をAPIで取得し、js側で利用しています。
jsだけの実装なので、公開はgithub pagesで行いました。(すべて無料!)
レコメンドの仕組み
ごはん165品には、以下の5つの指標で1〜10の点数をつけています。
・油っぽさ
・熱さ
・塩味
・甘味
・固体
ユーザーに5ステップの質問をすることで、ユーザーに対しても上記5つの指標の点数付けを行います。
これでユーザのペンタゴンと、ごはん165品のペンタゴンができますので、ペンタゴンの一致率が最も高いごはんをレコメンドするという仕組みです。
グラフ同士の一致率は「ユークリッド距離」という計算方法を利用しました。小難しそうですが、落ち着いて公式に当てはめれば以外とできます。
{d = \sqrt{(a_1 - b_1)^2 + (a_2 -b_2)^2 + (a_3 -b_3)^2 + ...+(a_i-b_i)^2}
}
以下はユーザーのペンタゴンとごはん全品のペンタゴンを比較し、一致度の高い順に並び替え、最も一致しているごはんをどっかに登録している部分のコードです。コード全体はgithubでご確認ください。
const suggest = async () => {
let points = {};
dishes.value.forEach(d => {
let n = 0;
Object.keys(tastes.value).forEach(k => {
n += Math.pow(Number(d[k]) - Number(tastes.value[k]), 2);
});
n = Math.sqrt(n)
points[d['id']] = n;
});
let sortedDishes = dishes.value.sort((a, b) => {
return points[a['id']] > points[b['id']] ? 1 : -1
});
result.value = sortedDishes[0];
store.commit('setDishes', sortedDishes);
}
Math.pow
が累乗で、Math.sqrt
が平方根です。
不思議な質問の正体
5つの質問はユーザーのペンタゴンを作成するためのものです。
色、乗り物、方角など、ごはんとは関係なさそうな質問からレコメンドしますが、
ユーザーのペンタゴンを作れれば、質問はなんでも良いので、よりおもしろいものを選びました。
ユーザーのペンタゴンは、デフォルトではすべて平均値となっており、
質問の回答次第で点数をプラスしたりマイナスしたりしています。
たとえば乗り物の質問では、以下のように点数が増減します。
{
"id": 33,
"name": "車",
"tastes": {
"heat": 0.5,
"oily": -0.5,
"salty": 0,
"solid": 1,
"sweetness": 0.5
}
},
{
"id": 34,
"name": "電車",
"tastes": {
"heat": -0.5,
"oily": -0.5,
"salty": 0.5,
"solid": 0,
"sweetness": 0.5
}
},
{
"id": 35,
"name": "船",
"tastes": {
"heat": 0.5,
"oily": 0.5,
"salty": 0.5,
"solid": -1,
"sweetness": -0.5
}
},
{
"id": 36,
"name": "飛行機",
"tastes": {
"heat": 1,
"oily": -1,
"salty": 0.5,
"solid": 1,
"sweetness": -0.5
}
},
これが適切なのかどうかは不明ですが、そこがおもしろいかなと思います。車と電車は甘くて、飛行機は熱いんでしょうか。不思議です。