【kintone】私っぽいつぶやきをつくるアプリ

こんにちは！
昔作ったアプリを掘り返していまして、
今回は、どうやって作ったかわからないアプリを復習を兼ねてもう一度構築する・・・。
という作業をしてみたいと思います。


参考にしたサイトは、書いていたソースを見たところ↓の2サイト🙏ありがとうございます🙏

[Node.jsでTinySegmenter、kuromoji、MeCabを使って分かち書きをしてみる](https://blog.kozakana.net/2019/04/try-tokenizer/)
[TinySegmenterでマルコフ連鎖。](https://pondad.net/bot/2016/05/30/markov.html)

# 私は何を作ったのか？
Twitterのつぶやきを適当に選んで登録しておいて、ボタンをクリックすると、隣のテキストエリアに私っぽいつぶやきを書いてくれるアプリ。です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/933187a6-191c-e5f0-11cc-c7c2a315e9d4.png)

# 私はこのソースをどこに書いたのか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/1e2b31b4-8acf-184e-ce09-d932c7b5a068.png)
アプリIDは49！
私は49番のソースを探すことにしました。

アプリ番号付けてフォルダー分けててよかったです。49番のソースはすぐに見つかりました。
しかしこのなんちゃって圧縮。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/8d6f7066-a525-53b5-a7b3-ce17556886e0.png)

結局私は、記憶をたどり、JavaScriptの勉強したフォルダーをしらみつぶしに探して発見。
mtestという名前のフォルダーだったけど、49_sourceという名前に変更しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/02302d4c-1b5d-a24e-42e4-5c0a4af85e23.png)

# ソースから参考サイトをたどる

`sub.js`というファイルの最初にこう書いてありました。

```js

export function tSentence(data){
    const TinySegmenter = require('tiny-segmenter');
    const segmenter = new TinySegmenter();
```

`TinySegmenter` というライブラリを使っているぽい。
私はググった。ググって見つけました。
それが冒頭にも紹介したこちら↓
[Node.jsでTinySegmenter、kuromoji、MeCabを使って分かち書きをしてみる](https://blog.kozakana.net/2019/04/try-tokenizer/)

しかしこれにはサンプルソースがついていない。

ソースの中にヒントはないか・・・！？
と思って、読んでいると、普段の私はあんまりコメントを書かないのに親切なコメントが書かれている部分がありました！

```js

//makeDic() で辞書に追加 
```

このコメントでググって見つけたのが、
冒頭にも紹介したこちら↓
[TinySegmenterでマルコフ連鎖。](https://pondad.net/bot/2016/05/30/markov.html)

あとはwebpackについては行きあたりばったりでググりながら作ったんだと思う。

# 私っぽいつぶやきをつくるアプリの作り方

やっとアプリの話です。

## アプリの準備
まずはアプリの作成。
文字列(複数行)を1つ準備する。
フィールドコードは`dic_data`としていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/d300f832-6bc4-37e0-abf4-c1ae5fd99c72.png)

## JavaScriptの準備

ではNode.jsを準備してみるよ。
過去のことなので忘れちゃったけど、まずはNode.jsをインストールします。
こちらから↓
https://nodejs.org/ja/

### フォルダーの準備
アプリ用のフォルダーを作成します。

私は、`226_myTweet`という名前のフォルダーを作りました。
※226はアプリID

そのフォルダーまでコマンドプロンプトなどで入りまして

`npm init`

としてEnterキーを連打したら

`package.json`

というファイルが作成されます。

### tiny-segmenterインストール

続けて、コマンドプロンプトなどでこう↓

`npm install tiny-segmenter`

すると、tiny-segmenterがインストールされます。
(tiny-segmenter)[https://www.npmjs.com/package/tiny-segmenter]

### webpackのインストール

順番前後しちゃったかもですが、webpackもインストールします。
この順に実行。

`npm install --save-dev webpack`
`npm install --save-dev webpack-cli`

それから、
`package.json`の`scripts`のところに
`"build":"webpack",`という1行を追加しておきます。

```json
～略～
  "scripts": {
    "build":"webpack",　←追加
    "test": "echo \"Error: no test specified\" && exit 1"
  },
～略～
```

### webpack.config.js　を作成する

`package.json`と同じフォルダーに`webpack.config.js`というファイルを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/16b760cc-3c21-3087-af5a-a3c3381cd483.png)


`webpack.config.js`の中身はこんなかんじですが、よく分かっていません。
modeには開発モード、プロダクションモードなどあるようです。
勉強しなくちゃ・・・！

```js

module.exports ={
  mode:"production",
  devServer:{
    contentBase:"dist",
    open:true
  },
};
```

### srcフォルダの作成とJavaScriptファイルの作成
またまた同じフォルダーに`src`フォルダーを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/78617edd-401e-2132-3bef-4d048ca6c233.png)

その中に2つのJavaScriptファイルを入れます。

1つ目`index.js`

```js
import { tSentence } from "./sub";

(()=> {

    'use strict';

    kintone.events.on(['app.record.index.show'],  event => {
        const sp = kintone.app.getHeaderMenuSpaceElement();
        
        //ボタン
        const btn = document.createElement('button');
        btn.textContent='ボタン';
        
        //テキストエリア
        const ta = document.createElement('textarea');
        ta.id ="tweet";
        ta.cols = 60;
        ta.rows = 3;   
        ta.style="line-height: normal;";

        sp.appendChild(btn);
        sp.appendChild(ta);

        //ボタンをクリックしたときの動作
        btn.onclick=()=>{
            kintone.api('/k/v1/records', 'GET', {'app': kintone.app.getId(),'fields':'dic_data'},resp=>{
                let data="";
                resp.records.forEach(v=>{
                    //辞書を作る
                    data += v.dic_data.value;
                });

                //辞書を元にマルコフ連鎖
                const txt = tSentence(data);

                document.getElementById("tweet").value = txt;
                console.log(txt);
            });
        }
        return event;
    });
})();


```


2つめ`sub.js`
こちらは冒頭で紹介したサイト内にあったソースに文字制限（140文字）だけ足して作ったものです。

```js
export function tSentence(data){
    const TinySegmenter = require('tiny-segmenter');
    const segmenter = new TinySegmenter();

    const dic = makeDic(data);
    let sentence;
    do{
        sentence = makeSentence(dic).replace(/\n/g,"");
    }
    while(sentence.length < 40 || sentence.length > 140)
   
    return sentence;

    //makeDic() で辞書に追加
    function makeDic(morphemes){
        morphemes = nonoise(morphemes);
        const lines = morphemes.split("。");
        const morpheme = new Object();
        for(let i = 0; i <= lines.length-1; i++){
            const words = segmenter.segment(lines[i]);
            if(! morpheme["_BOS_"] ){morpheme["_BOS_"]=new Array();}
            if(words[0]){morpheme["_BOS_"].push(words[0])};//文頭
            for(let w=0; w<=words.length-1; w++){
                const now_word = words[w];//今の単語
                let next_word = words[w+1];//次の単語
                if(next_word == undefined){//文末
                    next_word = "_EOS_"
                }
                if(! morpheme[now_word] ){
                    morpheme[now_word]=new Array();
                }
                morpheme[now_word].push(next_word);
                if(now_word == "、"){//「、」は文頭として使える。
                    morpheme["_BOS_"].push(next_word);
                }
            }
        }
        return morpheme;
    }
    //nonoise()ノイズ除去
    function nonoise(morphemes){
        morphemes = morphemes.replace(/\n/g,"。");
        morphemes = morphemes.replace(/[\?\!？！]/g,"。");
        morphemes = morphemes.replace(/[-|｜:：・]/g,"。");
        morphemes = morphemes.replace(/[「」（）\(\)\[\]【】]/g," ");
        return morphemes
    }
    // makeSentence()文章をシャッフル
    function makeSentence(morpheme){
        let now_word = morpheme["_BOS_"][Math.floor( Math.random() * morpheme["_BOS_"].length )];
        let morphemes = now_word;
        morphemes += now_word;
        while(now_word != "_EOS_"){
            now_word = morpheme[now_word][Math.floor( Math.random() * morpheme[now_word].length )];
            morphemes += now_word;
        }
        morphemes = morphemes.replace(/_EOS_$/,"。")
        return morphemes;
    }
}
```

## ビルドする

ここまでできたら、コマンドプロンプトでそのまま
`npm run build`
とします。

すると`dist`フォルダーが出現して、中に`main.js`というファイルが現れます！

この`main.js`をアプリにアップロードしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/3fa6bd46-2993-649e-ce1a-118588b71164.png)


# 動作確認

アプリの方に適当にツイートをコピって保存しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/eadfc9df-63f2-5d5f-bab8-5f667551a7b8.png)

ボタンをクリック！
すると・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/5b4f14a2-c791-e6ec-9a43-d042e3c12110.png)


もういっちょ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/66ec3855-760a-1310-fbed-6d4e9cf4e02a.png)

謎のつぶやき文言のできあがりです。（やった！）

# まとめ
TinySegmenterをつかえばなんとなく人工無能みたいなことができそうです。

何に使えるか？と言われたら困りますが、
webpackをつかって1つにまとめてupするということはやったことがあったので、ちょっと復習になりました。
よくわからないまま使っているところがあるので、ちゃんと勉強したいと思います。



では今日はこのへんで(・ω・)ﾉｼﾉｼ