CSVでbot風に受け答えをする[ユビキタ初音ミクv1.0]

# 概要

現在"ユビキタ初音ミクアプリ"というAndroidアプリを開発中です。(https://github.com/Aqua-ix/YoubiMiku)
初音ミクとチャットボット風に会話を行えるようにするのが目的です。

ミクさんらしい受け答えを行うために、APIなどを使用しない受け答えの実装方法として、単語に対する返答をCSVでとにかく沢山作る方法を用います。

最初に動作を見せてしまうと、以下のようになります。
![ezgif-4-0aef2bb2c3.gif](https://qiita-image-store.s3.amazonaws.com/0/189802/0f89effe-c86e-6783-994f-0f2707dea73d.gif)

# 実装

### CSV

CSVファイルを以下のように、単語、返答、表情の順に書きます。

```talks.csv
呼びかけ,返答,"表情(N,G,A,S)"
おはよう,おはようございます、マスター,N
こんにちは,こんにちはマスター。お元気ですか？,G
こんばんは,こんばんはマスター。,G
おやすみ,おやすみなさい。いい夢を！,N
ありがとう,どういたしまして、マスター!,G
```

行最後尾についているパラメータは表情です。静止画で表示されるミクさんの表情をコントロールします。

### Java

CSVファイルを読み込むtalkReaderクラスを作成します。

```talkReader.java

public class talkReader {
    List<ListData> talk = new ArrayList<ListData>();

    public void reader(Context context) {
        AssetManager assetManager = context.getResources().getAssets();
        try {
            // CSVファイルの読み込み
            InputStream inputStream = assetManager.open("talks.csv");
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferReader = new BufferedReader(inputStreamReader);
            String line;
            while ((line = bufferReader.readLine()) != null) {

                //カンマ区切りで１つづつ配列に入れる
                ListData data = new ListData();
                String[] RowData = line.split(",");

                //CSVの左([0]番目)から順番にセット
                data.setYou(RowData[0]);
                data.setMiku(RowData[1]);
                data.setFace(RowData[2]);

                talk.add(data);
            }
            bufferReader.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
```
読み込んだCSVをオブジェクト化するためのListDataクラスを作成します。

```ListData.java

public class ListData {
    String you;
    String miku;
    String face;

    public void setYou(String you) {
        this.you = you;
    }

    public String getYou() {
        return this.you;
    }

    public void setMiku(String miku) {
        this.miku = miku;
    }

    public String getMiku() {
        return this.miku;
    }

    public void setFace(String face) {
        this.face = face;
    }

    public String getFace() {
        return this.face;
    }
}
```

MainActivityでは読み込んだリストをfor文で回して、String.contains(String value)により一致した単語を見つけた時点で受け答えを表示するようにしています。
(以下onClick(View v)のみ抜粋)

```MainActicity.java
public void onClick(View v){
        EditText editText = (EditText) findViewById(R.id.yourText);
        TextView textView = (TextView)findViewById(R.id.MikuTalk);
        ImageView imageView = (ImageView)findViewById(R.id.face);
        String miku_talk;
        String your_talk = editText.getText().toString();
        editText.setText("");

        talkReader t = new talkReader();
        t.reader(getApplicationContext());
        ListData data = new ListData();

        for(int i=1;i<t.talk.size();i++) {
            data = t.talk.get(i);
            miku_talk = data.getMiku();
            if(your_talk.equals("")){
                textView.setText("You > \nMiku > 何か用かな?");
                imageView.setImageResource(R.drawable.normal);
                break;
            }
            else if (your_talk.contains(data.getYou())) {
                textView.setText("You > " + your_talk + "\nMiku > " + miku_talk);
                if(data.getFace().equals("N")){
                imageView.setImageResource(R.drawable.normal);
                }
                else if(data.getFace().equals("G")){
                    imageView.setImageResource(R.drawable.glad);
                }
                else if(data.getFace().equals("A")){
                    imageView.setImageResource(R.drawable.angry);
                }
                else if(data.getFace().equals("S")){
                    imageView.setImageResource(R.drawable.sad);
                }
                break;
            } else {
                textView.setText("You > " + your_talk + "\nMiku > 「" + your_talk + "」という言葉は分かりません。ごめんね。");
                imageView.setImageResource(R.drawable.normal);
            }
        }

        if(v.getId()==R.id.reset_Button) {
            textView.setText(defaultText);
            editText.setText("");
            imageView.setImageResource(R.drawable.normal);
        }

    }
```