アイデアの相互評価ができるidea streamerを作りたかったああああ


アイデアの評価むつかしい問題

最近世の中でアート思考だとかデザイン思考だとかがもてはやされるようになった気がします。
でも誰か知り合いが出したアイデアって、忖度なしで評価するの結構難しいと思うんですよね。
例えば上司のアイデアだったら「いいですね!」と言ってしまいそうですし、斬新なアイデアであっても、「こいつ生意気やんけ」といって評価を下げてしまう人もいるかもしれません。

今回は「ひたすらアイデアを投稿しまくって」「それを知らない誰かに評価してもらえるidea streamerというプラットフォームを作ってみました。
途中バグがあったり画面遷移がうまくいかなかったりで、超未完成ですが一旦振り返りの意味で投稿してみたいと思います。
アイデアの相互評価」という意味で面白い仕組みだと思うので、何か刺激になればなと思います。

アプリはこちらから入って、途中で画面遷移が切れるのでアイデア評価からはこちらからお願いします!

動作デモ

アイデアのブレスト

3分間の間にひたすらアイデアを投稿しまくっていきます。
Keywordに自分の好きな単語を入れておくと、「×〇〇」の部分がランダムで変わっていきます(技術不足で途中バグってます)。
普段交じり合わない組み合わせからアイデアを発想して投稿しまくる、という感じですね。

アイデアの評価

アイデア出しが終わったら次は知らない人が投稿したアイデアの評価を行います (画面遷移の実装ができてません)。
DBにあるアイデアを見て面白い・斬新だな、などの観点で0~10の間で評価します。
現状自分のアイデアも見れるようになっていますが、そうすると自己評価になって意味がないので、他の人のアイデアだけ取り出す処理が必要そうですね。

アイデアのスコアの確認

こちらは全く実装できてません。
自分のアイデアがどう評価されたのかを確認できるようにしたいですね。

できたこととできなかったこと

実装できた

・アイデア出しする仕組み
・アイデア評価する画面
・全体の雰囲気

実装できなかった

・アイデア評価の仕組み
・自分のアイデアのスコア確認
・全部0点にしちゃうなど悪ふざけ対策
・画像がデフォルト

悔しい。。。

実装こまごま

yarnでいろいろ

今回は初めてNuxt.jsを使って実装してみました。
結構癖があるけれど使いこなせたら楽しそう。
備忘録的に記録しておきます。

$ yarn create nuxt-app myNuxtTest
Project name: myNuxtTest
Programming language: JavaScript
Package manager: Yarn
UI framework: Bootstrap
Nuxt.js modules: Axios, Progressive Web App (PWA), Content
Linking tools: (Press <space> to select, <a> to toggle all, <i> to invert election)
Testing framework: None
Rendering mode: Universal (SSR / SSG)
Deployment target: Static (Static/JAMStack hosting)
Development tools: None
$ cd myNuxtTest

pagesの中に画面を作ったり、componentsにコンポを作り終わったら、

$ yarn dev

を実行後localhost:3000へアクセスし、画面を確認します。上手く動作していれば、

$ yarn generate

でhtmlを生成し、distフォルダをデプロイ、という流れです。
generateしてフォルダ構造がどう変化するかをちゃんと把握していなかったため、画面遷移がうまくできなかったです。。。悔しい。

Netlifyにデプロイしたのち、freenomで取得したドメインでURLを生成しました。
freenomは今回初めて使いましたがこんなにお手軽にドメインが借りれるのは驚きですね。

タイマーがゼロになったら次へ

カウントダウンタイマーはこちらのサイトを参考にさせていただきました。
カウントがゼロになったら自動で画面遷移するようにしたかったものの、うまく実装ができず。。。
ひとまずはv-showで表示非表示を制御して、ユーザにクリックしてもらう作戦に変更しました。

<template>
<div>
    <div v-show="show">
        <div id="timer">
            <div class="timer">
                <div class="time">
                    {{ formatTime }}
                </div>
            </div>
        </div>

         <h3>
            <input v-model="key" placeholder="KeyWord" class="key"> × {{reactant}} = <input v-model="idea" placeholder="Input Your Idea" class="idea">
         </h3>
         <br>
         <h3>
            <button v-on:click='random' class="button--green">Pass</button>
            <button v-on:click='post' class="button--green">Post</button>
        </h3>
    </div>
    <div v-show="shownext">
        <a
            href="ScoreIdea"
            target="_blank"
            rel="noopener noreferrer"
            class="button--green"
        >
            Next Step
        </a>
    </div>
</div>
</template>

script部分はカウントダウンする部分の処理と、データをDBへPostする処理を実装しました。
vueのライフサイクルをまだ理解しておらず、createdやmountedが使いこなせていないです。。。
いやあこのあたりもちゃんと理解したい。


<script>
import firebase from "firebase/app";
import "firebase/firestore";

export default {
    components: {},

    data(){
        return{
            db: {},
            reactant: 'Click Pass',
            allData: ["文化","コロナ","","飲む","食べ物","おいしい","恋愛","決める","地面"],
            show:true,
            shownext:false,
            min: 2,
            sec: 59,
            timerOn: false,
            timerObj: null,
        }
    },

    methods: {
        //初期化
        init: () => {
            const config = {
                //firebaseの情報
                };

            // Initialize Firebase
            firebase.initializeApp(config);
            },

        //カウントダウン処理
        count: function() {
            if (this.sec <= 0 && this.min >= 1) {
                this.min --;
                this.sec = 59;
            } else if(this.sec <= 0 && this.min <= 0) {
                this.complete();
            } else {
                this.sec --;
            }
        },

        //カウントがゼロになった処理
        complete: function() {
            clearInterval(this.timerObj)
            this.show = false;
            this.shownext = true;
        },

        //ボタンを押したらランダムに表示
        random: function(){
            const rnd = Math.floor(Math.random() * this.allData.length);
            this.reactant = this.allData[rnd]
        },

        //データ追加の処理
        post: function(){
            const testId = firebase.firestore().collection('test').doc().id; //ユニークなIDを生成
            const docRef = firebase.firestore().collection('test').doc(testId);
            const setAda = docRef.set({
                key: this.key,
                reactant:this.reactant,
                idea:this.idea
            });
            this.random();
            this.idea = "";
            //window.location.href = "JoinTable";
        },

        //データ取得の処理
        get: function(){
            //this.allData = [];
            firebase.firestore().collection('test').get().then(snapshot => {
                snapshot.forEach(doc => {
                    console.log(doc);
                    this.allData.push(doc.data());
                })
            });
            this.random();
        }

    },

    //インスタンスが生成したときの処理
    created(){
        let self = this;
        this.timerObj = setInterval(function() {self.count()}, 1000)
        this.timerOn = true; //timerがOFFであることを状態として保持
    },

    //常に動く処理
    computed: {
        formatTime: function() {
        let timeStrings = [
            this.min.toString(),
            this.sec.toString()
        ].map(function(str) {
            if (str.length < 2) {
            return "0" + str
            } else {
            return str
            }
        })
        return timeStrings[0] + ":" + timeStrings[1]
        }
    },

    //マウントされたときの処理
    mounted(){
        this.init();
        this.get();
    },
}
</script> 

あとはデザイン部分ですね。
これはほとんどデフォルトのものを利用しています。


<style>
input{
    text-align: center;
}
input.key{
    width:160px;
    height:50px;
    }

input.idea{
    width:260px;
    height:50px;
    }

#timer {
  display: flex;
  align-items: center;
  justify-content: center;
}
.time {
  font-size: 100px;
}
</style>

さいごに

フレームワークの便利さを感じれるほどまだ慣れておらず、この辺りは経験積んでいくしかないですね。
この辺は精進していかなきゃなあと思います。
アイデア自体は悪くないと思うのに悔しい。。。

最後までご覧になっていただきありがとうございました!
LGTMしていただけると励みになりますので、是非是非よろしくお願いします!