【Nuxt.js + COTOHA API + microCMS】COTOHAチックなフラッシュカード作ってみた

## 0. はじめに
タイトルの通りですが、**【Nuxt.js + COTOHA API + microCMS】**を使って**COTOHAチックなフラッシュカード**を作ってみました！

以下の参加記事になります！

- [**【Qiita x COTOHA APIプレゼント企画】COTOHA APIで、テキスト解析をしてみよう！**](https://zine.qiita.com/event/collaboration-cotoha-api/?utm_source=qiita&utm_medium=top_banner)

COTOHA APIを使ってこんなのも作ってます！

- [**【LINE BOT + COTOHA API】君の文章は相手を不快にしていないか？COTOHA先生にチェックしてもらおうぜ**](https://qiita.com/i-tanaka730/items/a32b3ce7ca8c7edc9634)

~~ちなみに息子(2歳)へのクリスマスプレゼントを華麗に失敗した私が狙うのは「作ろうきのこの山」です。:santa:~~

## 1. 概要

こんな感じで動作しています＼(^o^)／

①microCMSにて、テキストエリアに以下のような文章を登録。

```
NTTコミュニケーションズ提供の自然言語解析APIはcotoha apiである。
```

②フラッシュカードを起動したタイミングで、①のデータを取得。

③COTOHA APIの**キーワード抽出**を使って、②の文章から最も重要度の高いキーワードを抽出。

④抽出したキーワードを**＼(^o^)／**に変換し、問題文とする。


## 2. 環境
- Nuxt.js
- COTOHA API
- microCMS

## 3. プログラム
```vuejs:index.vue
<template>
  <div class="container">
    <b-card tag="article" style="width: 30rem;" class="mb-2">
      <h2><b-badge variant="success">COTOHA FLASH CARD</b-badge></h2>
      <br/>
      <b-card-text>{{ question }}</b-card-text>
      <br/>
      <b-dropdown variant="success" id="dropdown-1" text="答え" class="m-md-2">
        <b-dropdown-item>{{ answer }}</b-dropdown-item>
      </b-dropdown>
      <b-button variant="success" v-on:click="nextQuestion">次の問題</b-button>
    </b-card>
  </div>
</template>

<script>

import CotohaApi from './cotoha'
import FlashCard from './flashcard'

const MICRO_CMS_API_KEY = "**********"
const DEVELOPER_API_CRIENT_ID = "**********"
const DEVELOPER_API_CRIENT_SECRET = "**********"

const cotohaApi = new CotohaApi(DEVELOPER_API_CRIENT_ID, DEVELOPER_API_CRIENT_SECRET)
const flashCard = new FlashCard(MICRO_CMS_API_KEY)

export default {

  async asyncData () {
    const questions = await flashCard.getAllQuestions()
    const question = flashCard.getQuestionAtRandom(questions)
    const answer = await cotohaApi.getKeyword(question)
    const emoticonQuestion = flashCard.convertEmoticonQuestion(question, answer)

    return {
      questions : questions,
      question : emoticonQuestion,
      answer : answer
    }
  },

  methods: {
    nextQuestion: async function() {
      const question = flashCard.getQuestionAtRandom(this.questions)
      const answer = await cotohaApi.getKeyword(question)
      const emoticonQuestion = flashCard.convertEmoticonQuestion(question, answer)

      this.question = emoticonQuestion
      this.answer = answer
    }
  }
}

</script>

<style>
.container {
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.title {
  font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,
    'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  display: block;
  font-weight: 300;
  font-size: 100px;
  color: #35495e;
  letter-spacing: 1px;
}

.subtitle {
  font-weight: 300;
  font-size: 42px;
  color: #526488;
  word-spacing: 5px;
  padding-bottom: 15px;
}

.links {
  padding-top: 15px;
}
</style>

```

```javascript:cotoha.js
import axios from 'axios'

export default class CotohaApi {

  DEVELOPER_API_KEYWORD_URL = "https://api.ce-cotoha.com/api/dev/nlp/v1/keyword"
  ACCESS_TOKEN_PUBLISH_URL = "https://api.ce-cotoha.com/v1/oauth/accesstokens"

  constructor(crientId, crientSecret) {
    this.crientId = crientId
    this.crientSecret = crientSecret
  }

  async getAccessToken() {
    const tokenHeaders = {
      headers:{
        "Content-Type": "application/json"
      }
    }

    const tokenData = {
      "grantType": "client_credentials",
      "clientId": this.crientId,
      "clientSecret": this.crientSecret
    }
  
    const tokenResult = await axios.post(this.ACCESS_TOKEN_PUBLISH_URL, tokenData, tokenHeaders)
    const accessToken = tokenResult.data.access_token
    return accessToken
  }
  
  async getKeyword(document, keywordNum = 1) {
    const token = await this.getAccessToken()

    const parseHeaders = {
      headers:{
        "Content-Type": "application/json",
        "Authorization": "Bearer " + token
      }
    }
  
    const parseData = {
      "document": document,
      "max_keyword_num": keywordNum
    }
  
    const parseResult = await axios.post(this.DEVELOPER_API_KEYWORD_URL, parseData, parseHeaders)
    const keyword = parseResult.data.result[0].form
    return keyword
  } 
}
```

```javascript:flashcard.js
import axios from 'axios'
import Enumerable from 'linq'

export default class FlashCard {

  MICRO_CMS_QUESTION_URL = "https://cotoha-flash-card.microcms.io/api/v1/question"

  constructor(microCmsKey) {
    this.microCmsKey = microCmsKey
  }

  async getAllQuestions() {
    const apiHeaders = {
      headers:{
        "X-API-KEY": this.microCmsKey
      }
    }

    const questionResult = await axios.get(this.MICRO_CMS_QUESTION_URL, apiHeaders)
    const contents = Enumerable.from(questionResult.data.contents)
    const questions = contents.select(c => c.question).toArray()
    return questions
  }
  
  getQuestionAtRandom(questions) {
    const index = Math.floor(Math.random() * questions.length)
    return questions[index]
  }
  
  convertEmoticonQuestion(question, answer) {
    const emoticonQuestion = question.replace(answer, "＼(^o^)／")
    return emoticonQuestion
  }
}
```

## 4. デモ
![card.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247638/567e8732-8191-f953-221a-449ce4a68891.gif)

## 5. 参考
microCMSについては、**@ohnaka0410**さんの記事を参考にさせて頂きました＼(^o^)／

- [**ヘッドレスCMS × Static Site GeneratorでJamstackな爆速表示サイトを作ってみるチュートリアル**](https://qiita.com/ohnaka0410/items/c2f6d7c90330c1d97c69)

## 6. おわりに
QiitaのCOTOHA記事を見てると、みなさん面白いアイデア出しまくりで、とても勉強になります！

**COTOHA楽しい＼(^o^)／**